diff --git a/app/Concerns/Auditable.php b/app/Concerns/Auditable.php index 5cbb81f..ae1a097 100644 --- a/app/Concerns/Auditable.php +++ b/app/Concerns/Auditable.php @@ -3,7 +3,6 @@ namespace App\Concerns; use App\Models\AuditLog; -use Illuminate\Database\Eloquent\Model; /** * Enregistre automatiquement les créations / modifications / suppressions @@ -16,9 +15,9 @@ trait Auditable { public static function bootAuditable(): void { - static::created(fn (Model $model) => $model->recordAudit('created', null, $model->auditableAttributes())); + static::created(fn (self $model) => $model->recordAudit('created', null, $model->auditableAttributes())); - static::updated(function (Model $model): void { + static::updated(function (self $model): void { $changed = array_keys($model->getChanges()); $keys = array_diff($changed, $model->auditExcluded()); if ($keys === []) { @@ -31,7 +30,7 @@ public static function bootAuditable(): void $model->recordAudit('updated', $old, $new); }); - static::deleted(fn (Model $model) => $model->recordAudit('deleted', $model->auditableAttributes(), null)); + static::deleted(fn (self $model) => $model->recordAudit('deleted', $model->auditableAttributes(), null)); } /** Champs exclus du journal (secrets et bruit). */ diff --git a/app/Console/Commands/GenerateStudentMatricule.php b/app/Console/Commands/GenerateStudentMatricule.php index e8f8206..8ead8a8 100644 --- a/app/Console/Commands/GenerateStudentMatricule.php +++ b/app/Console/Commands/GenerateStudentMatricule.php @@ -3,8 +3,8 @@ namespace App\Console\Commands; use App\Models\Student; -use App\Services\MatriculeService; use Illuminate\Console\Command; +use Illuminate\Database\Eloquent\Collection; class GenerateStudentMatricule extends Command { @@ -13,10 +13,10 @@ class GenerateStudentMatricule extends Command * * @var string */ - protected $signature = 'matricule:generate-student + protected $signature = 'matricule:generate-student {--class-id= : ID de la classe} {--all : Générer pour tous les élèves} - {--registration : Générer aussi les numéros d\'enregistrement} + {--matricule : Générer aussi les matricules des élèves} {--force : Forcer la régénération}'; /** @@ -31,10 +31,9 @@ class GenerateStudentMatricule extends Command */ public function handle(): int { - $matriculeService = app(MatriculeService::class); + $withStudentMatricule = (bool) $this->option('matricule'); if ($this->option('all')) { - // Générer pour tous les élèves $students = Student::all(); if ($students->isEmpty()) { @@ -44,28 +43,7 @@ public function handle(): int } $this->info("Génération des matricules pour {$students->count()} élèves..."); - - $progressBar = $this->output->createProgressBar($students->count()); - $progressBar->start(); - - foreach ($students as $student) { - // Générer matricule de l'utilisateur - if (! $student->user->natricule) { - $student->user->natricule = $student->user->generateMatricule(); - $student->user->save(); - } - - // Générer numéro d'enregistrement - if (! $student->registration_number) { - $student->registration_number = $student->generateRegistrationNumber(); - $student->save(); - } - - $progressBar->advance(); - } - - $progressBar->finish(); - $this->newLine(); + $this->backfillMatricules($students, $withStudentMatricule); $this->info('✅ Matricules générés avec succès!'); return 0; @@ -88,18 +66,32 @@ public function handle(): int } $this->info("Génération pour {$students->count()} élèves..."); + $this->backfillMatricules($students, $withStudentMatricule); + $this->info('✅ Matricules générés avec succès!'); + return 0; + } + + /** + * Génère les matricules manquants pour un lot d'élèves. + * + * @param Collection $students + */ + private function backfillMatricules(Collection $students, bool $withStudentMatricule): void + { $progressBar = $this->output->createProgressBar($students->count()); $progressBar->start(); foreach ($students as $student) { + // Matricule du compte utilisateur associé. if (! $student->user->natricule) { $student->user->natricule = $student->user->generateMatricule(); $student->user->save(); } - if (! $student->registration_number) { - $student->registration_number = $student->generateRegistrationNumber(); + // Matricule de l'élève (optionnel, via --matricule). + if ($withStudentMatricule && empty($student->matricule)) { + $student->matricule = $student->generateMatricule(); $student->save(); } @@ -108,8 +100,5 @@ public function handle(): int $progressBar->finish(); $this->newLine(); - $this->info('✅ Matricules générés avec succès!'); - - return 0; } } diff --git a/app/Http/Controllers/Administration/SubjectAssignmentController.php b/app/Http/Controllers/Administration/SubjectAssignmentController.php index 08112f6..707d88b 100644 --- a/app/Http/Controllers/Administration/SubjectAssignmentController.php +++ b/app/Http/Controllers/Administration/SubjectAssignmentController.php @@ -91,8 +91,8 @@ public function statistics(Request $request): Response $assignments = $selected ? $this->teacherAssignments($teacherId, $yearFilter)->map(fn ($a) => [ 'id' => $a->id, - 'subject' => $a->subject?->name ?? '—', - 'classroom' => $a->classroom?->name ?? '—', + 'subject' => $a->subject->name ?? '—', + 'classroom' => $a->classroom->name ?? '—', 'active' => (bool) $a->active, ]) : collect(); @@ -143,7 +143,7 @@ public function exportStatistics(Request $request) 'assignments' => $this->teacherAssignments($teacher->id, $yearId), ])->setPaper('a4', 'portrait'); - return $pdf->stream('affectations-'.Str::slug(trim($teacher->firstname.' '.$teacher->lastname).'-'.($year?->year ?? '')).'.pdf'); + return $pdf->stream('affectations-'.Str::slug(trim($teacher->firstname.' '.$teacher->lastname).'-'.($year->year ?? '')).'.pdf'); } /** Identifiant de l'année académique active (la plus récente marquée active). */ @@ -170,7 +170,7 @@ private function teacherAssignments(string $teacherId, string $yearId): Collecti ->where('teacher_id', $teacherId) ->where('academic_year_id', $yearId) ->get() - ->sortBy(fn ($a) => ($a->subject?->name ?? '').' '.($a->classroom?->name ?? '')) + ->sortBy(fn ($a) => ($a->subject->name ?? '').' '.($a->classroom->name ?? '')) ->values(); } diff --git a/app/Http/Controllers/Api/ApiController.php b/app/Http/Controllers/Api/ApiController.php index 9dd0da7..48783eb 100644 --- a/app/Http/Controllers/Api/ApiController.php +++ b/app/Http/Controllers/Api/ApiController.php @@ -18,6 +18,9 @@ abstract class ApiController extends Controller */ protected function accessibleStudents(Request $request): Collection { + // Ces routes API authentifient un élève ou un tuteur (gardes Sanctum + // dédiées), jamais le User par défaut supposé par l'analyse statique. + /** @var Student|Guardian|null $user */ $user = $request->user(); if ($user instanceof Student) { @@ -38,6 +41,7 @@ protected function accessibleStudents(Request $request): Collection */ protected function resolveStudent(Request $request, string $studentId): Student { + /** @var Student|Guardian|null $user */ $user = $request->user(); if ($user instanceof Student) { diff --git a/app/Http/Controllers/Api/V1/AuthController.php b/app/Http/Controllers/Api/V1/AuthController.php index 7b8962f..e8da050 100644 --- a/app/Http/Controllers/Api/V1/AuthController.php +++ b/app/Http/Controllers/Api/V1/AuthController.php @@ -39,6 +39,8 @@ public function login(LoginRequest $request): JsonResponse public function me(Request $request): JsonResponse { + // Portail parent/élève : le principal authentifié est un tuteur ou un élève. + /** @var Guardian|Student $user */ $user = $request->user(); $type = $user instanceof Guardian ? 'guardian' : 'student'; @@ -47,7 +49,9 @@ public function me(Request $request): JsonResponse public function logout(Request $request): JsonResponse { - $request->user()->currentAccessToken()->delete(); + /** @var Guardian|Student $user */ + $user = $request->user(); + $user->currentAccessToken()->delete(); return response()->json(['message' => 'Déconnecté.']); } diff --git a/app/Http/Controllers/Api/V1/ChildrenController.php b/app/Http/Controllers/Api/V1/ChildrenController.php index 58edffc..b72c98f 100644 --- a/app/Http/Controllers/Api/V1/ChildrenController.php +++ b/app/Http/Controllers/Api/V1/ChildrenController.php @@ -16,6 +16,7 @@ public function index(Request $request): AnonymousResourceCollection { $withActiveEnrollment = ['enrollments' => fn ($q) => $q->where('status', Enrollment::STATUS_ACTIVE)->with('classroom:id,name')]; + /** @var Student|Guardian $user */ $user = $request->user(); if ($user instanceof Student) { diff --git a/app/Http/Controllers/Api/V1/DashboardController.php b/app/Http/Controllers/Api/V1/DashboardController.php index 90a3101..7ca4251 100644 --- a/app/Http/Controllers/Api/V1/DashboardController.php +++ b/app/Http/Controllers/Api/V1/DashboardController.php @@ -45,7 +45,7 @@ public function index(Request $request): JsonResponse 'id' => $e->id, 'title' => $e->title, 'type' => $e->type, - 'start_date' => $e->start_date?->format('Y-m-d'), + 'start_date' => $e->start_date->format('Y-m-d'), ]); return response()->json([ diff --git a/app/Http/Controllers/Archives/ArchiveController.php b/app/Http/Controllers/Archives/ArchiveController.php index 6eadf88..3ead58e 100644 --- a/app/Http/Controllers/Archives/ArchiveController.php +++ b/app/Http/Controllers/Archives/ArchiveController.php @@ -16,8 +16,6 @@ class ArchiveController extends Controller { - private const TYPES = ['student' => Student::class, 'classroom' => Classroom::class]; - private function authorizeManage(Request $request): void { // Socle de sécurité : les routes portent déjà la permission fine (create/edit/ @@ -234,9 +232,12 @@ private function linkLabel(ArchivedDocument $d): ?string return null; } - return match ($d->documentable_type) { - Student::class => 'Élève : '.$d->documentable->name, - Classroom::class => 'Classe : '.$d->documentable->name, + $linked = $d->documentable; + + return match (true) { + // Un élève n'a pas de colonne « name » : on compose nom + prénom. + $linked instanceof Student => 'Élève : '.trim($linked->firstname.' '.$linked->lastname), + $linked instanceof Classroom => 'Classe : '.$linked->name, default => null, }; } diff --git a/app/Http/Controllers/CalendarEventController.php b/app/Http/Controllers/CalendarEventController.php index 60c48a3..7a8bce3 100644 --- a/app/Http/Controllers/CalendarEventController.php +++ b/app/Http/Controllers/CalendarEventController.php @@ -28,7 +28,7 @@ public function index(Request $request): Response 'title' => $e->title, 'description' => $e->description, 'type' => $e->type, - 'start_date' => $e->start_date?->format('Y-m-d'), + 'start_date' => $e->start_date->format('Y-m-d'), 'end_date' => $e->end_date?->format('Y-m-d'), 'all_day' => $e->all_day, 'start_time' => $e->start_time, diff --git a/app/Http/Controllers/Comptabilite/CashAccountController.php b/app/Http/Controllers/Comptabilite/CashAccountController.php index e982222..a70b40d 100644 --- a/app/Http/Controllers/Comptabilite/CashAccountController.php +++ b/app/Http/Controllers/Comptabilite/CashAccountController.php @@ -15,7 +15,7 @@ class CashAccountController extends Controller public function index(): Response { $accounts = CashAccount::withCount('payments') - ->withSum('transactions as total_income', 'amount', fn ($q) => $q->where('type', 'INCOME')) + ->withSum(['transactions as total_income' => fn ($q) => $q->where('type', 'INCOME')], 'amount') ->orderBy('type') ->orderBy('name') ->get(); diff --git a/app/Http/Controllers/Comptabilite/InvoiceController.php b/app/Http/Controllers/Comptabilite/InvoiceController.php index e870f9c..33378cb 100644 --- a/app/Http/Controllers/Comptabilite/InvoiceController.php +++ b/app/Http/Controllers/Comptabilite/InvoiceController.php @@ -169,7 +169,7 @@ public function verifyReceipt(Request $request): Response 'valid' => true, 'receipt_number' => $receipt->receipt_number, 'amount' => (float) $receipt->payment->amount, - 'paid_at' => $receipt->payment->paid_at?->format('d/m/Y'), + 'paid_at' => $receipt->payment->paid_at->format('d/m/Y'), 'student' => $receipt->payment->invoice?->enrollment?->student ? $receipt->payment->invoice->enrollment->student->lastname.' '.$receipt->payment->invoice->enrollment->student->firstname : null, diff --git a/app/Http/Controllers/Comptabilite/SituationController.php b/app/Http/Controllers/Comptabilite/SituationController.php index aa2d864..6a0a856 100644 --- a/app/Http/Controllers/Comptabilite/SituationController.php +++ b/app/Http/Controllers/Comptabilite/SituationController.php @@ -93,10 +93,10 @@ classes.code AS cl 'lastname' => $e->student?->lastname, 'matricule' => $e->student?->matricule, 'invoice_number' => $e->invoice?->invoice_number, - 'total' => (float) ($e->invoice?->total ?? 0), - 'amount_paid' => (float) ($e->invoice?->amount_paid ?? 0), - 'amount_remaining' => (float) ($e->invoice?->amount_remaining ?? 0), - 'status' => $e->invoice?->status ?? 'ISSUED', + 'total' => (float) ($e->invoice->total ?? 0), + 'amount_paid' => (float) ($e->invoice->amount_paid ?? 0), + 'amount_remaining' => (float) ($e->invoice->amount_remaining ?? 0), + 'status' => $e->invoice->status ?? 'ISSUED', ]); } @@ -153,14 +153,14 @@ public function export(Request $request) foreach ($enrollments as $e) { $inv = $e->invoice; fputcsv($out, [ - $e->student?->matricule ?? '—', - $e->student?->lastname ?? '—', - $e->student?->firstname ?? '—', - $e->classroom?->name ?? '—', - $inv?->invoice_number ?? '—', - number_format((float) ($inv?->total ?? 0), 0, ',', ' '), - number_format((float) ($inv?->amount_paid ?? 0), 0, ',', ' '), - number_format((float) ($inv?->amount_remaining ?? 0), 0, ',', ' '), + $e->student->matricule ?? '—', + $e->student->lastname ?? '—', + $e->student->firstname ?? '—', + $e->classroom->name ?? '—', + $inv->invoice_number ?? '—', + number_format((float) ($inv->total ?? 0), 0, ',', ' '), + number_format((float) ($inv->amount_paid ?? 0), 0, ',', ' '), + number_format((float) ($inv->amount_remaining ?? 0), 0, ',', ' '), $this->statusLabel($inv?->status), ], ';'); } diff --git a/app/Http/Controllers/Dashboard/DashboardController.php b/app/Http/Controllers/Dashboard/DashboardController.php index f683f97..01dfcb8 100644 --- a/app/Http/Controllers/Dashboard/DashboardController.php +++ b/app/Http/Controllers/Dashboard/DashboardController.php @@ -115,12 +115,12 @@ public function index(Request $request): Response 'id' => $p->id, 'amount' => (float) $p->amount, 'payment_method' => $p->payment_method, - 'paid_at' => $p->paid_at?->toDateString(), + 'paid_at' => $p->paid_at->toDateString(), 'cash_account' => $p->cashAccount?->name, 'student_name' => $p->invoice?->enrollment?->student ? $p->invoice->enrollment->student->firstname.' '.$p->invoice->enrollment->student->lastname : '—', - 'class_name' => $p->invoice?->enrollment?->classroom?->name ?? '—', + 'class_name' => $p->invoice?->enrollment?->classroom->name ?? '—', ]); /* Élèves avec aucun paiement (status ISSUED) — top 5 restant le + élevé */ @@ -193,14 +193,14 @@ public function index(Request $request): Response ->map(fn ($e) => [ 'id' => $e->id, 'enrollment_code' => $e->enrollment_code, - 'enrollment_date' => $e->enrollment_date?->toDateString(), + 'enrollment_date' => $e->enrollment_date->toDateString(), 'status' => $e->status, 'student_name' => $e->student ? $e->student->firstname.' '.$e->student->lastname : '—', 'matricule' => $e->student?->matricule, - 'class_name' => $e->classroom?->name ?? '—', - 'class_code' => $e->classroom?->code ?? '—', + 'class_name' => $e->classroom->name ?? '—', + 'class_code' => $e->classroom->code ?? '—', ]); /* Répartition des inscriptions par classe (pour le graphe) */ @@ -265,8 +265,8 @@ public function index(Request $request): Response 'id' => $p->id, 'student_name' => $p->student ? $p->student->lastname.' '.$p->student->firstname : '—', 'reason' => $p->reason, - 'start_date' => $p->start_date?->format('d/m/Y'), - 'end_date' => $p->end_date?->format('d/m/Y'), + 'start_date' => $p->start_date->format('d/m/Y'), + 'end_date' => $p->end_date->format('d/m/Y'), ]); /* Prochains examens officiels */ @@ -307,6 +307,8 @@ public function index(Request $request): Response ->first(['id', 'name']); // Bulletins figés (locked_at) de l'année (et de la période courante le cas échéant). + // Agrégat sans GROUP BY : toujours une ligne, colonnes calculées. + /** @var object{validated: int|string, avg_general: float|int|string|null} $rc */ $rc = ReportCard::query() ->whereNotNull('locked_at') ->when($yearId, fn ($q) => $q->where('academic_year_id', $yearId)) @@ -332,10 +334,10 @@ public function index(Request $request): Response $myAssignments = $assignments->map(fn ($a) => [ 'id' => $a->id, - 'subject' => $a->subject?->name ?? '—', + 'subject' => $a->subject->name ?? '—', 'class_id' => $a->class_id, - 'class_name' => $a->classroom?->name ?? '—', - 'class_code' => $a->classroom?->code ?? '—', + 'class_name' => $a->classroom->name ?? '—', + 'class_code' => $a->classroom->code ?? '—', ]); /* Emploi du temps du jour (1=lundi … 6=samedi) */ @@ -350,8 +352,8 @@ public function index(Request $request): Response 'id' => $s->id, 'start_time' => substr((string) $s->start_time, 0, 5), 'end_time' => substr((string) $s->end_time, 0, 5), - 'subject' => $s->subject?->name ?? '—', - 'class_name' => $s->classroom?->name ?? '—', + 'subject' => $s->subject->name ?? '—', + 'class_name' => $s->classroom->name ?? '—', 'room' => $s->room, ]); @@ -378,9 +380,9 @@ public function index(Request $request): Response ->get() ->map(fn ($e) => [ 'id' => $e->id, - 'name' => $e->template?->name ?? 'Évaluation', - 'subject' => $e->classSubject?->subject?->name ?? '—', - 'class_name' => $e->classSubject?->class?->name ?? '—', + 'name' => $e->template->name ?? 'Évaluation', + 'subject' => $e->classSubject?->subject->name ?? '—', + 'class_name' => $e->classSubject?->class->name ?? '—', 'date' => $e->date?->format('d/m/Y'), ]); diff --git a/app/Http/Controllers/Eleves/EnrollmentController.php b/app/Http/Controllers/Eleves/EnrollmentController.php index 9fc5fc3..f2216fa 100644 --- a/app/Http/Controllers/Eleves/EnrollmentController.php +++ b/app/Http/Controllers/Eleves/EnrollmentController.php @@ -86,6 +86,9 @@ public function index(Request $request): Response ->where('invoices.status', '!=', 'CANCELLED'); $applyFilters($aggQuery); + // Agrégat sans GROUP BY : renvoie toujours exactement une ligne de synthèse + // dont les colonnes sont calculées (invisibles à l'analyse statique). + /** @var object{billed: int|float|string, collected: int|float|string, remaining: int|float|string, unpaid_count: int|float|string, unpaid_amount: int|float|string} $agg */ $agg = $aggQuery->selectRaw(' COALESCE(SUM(invoices.total), 0) as billed, COALESCE(SUM(invoices.amount_paid), 0) as collected, diff --git a/app/Http/Controllers/Eleves/RosterController.php b/app/Http/Controllers/Eleves/RosterController.php index b84b80a..92a2d04 100644 --- a/app/Http/Controllers/Eleves/RosterController.php +++ b/app/Http/Controllers/Eleves/RosterController.php @@ -30,7 +30,7 @@ public function index(Request $request): Response // Année par défaut : celle demandée, sinon l'année active if ($yearId === '') { - $yearId = $activeYear?->id ?? ''; + $yearId = $activeYear->id ?? ''; } $classrooms = Classroom::where('active', true)->orderBy('name')->get(['id', 'name', 'code']); @@ -59,7 +59,7 @@ public function index(Request $request): Response 'student_name' => $e->student ? $e->student->lastname.' '.$e->student->firstname : '—', 'matricule' => $e->student?->matricule, 'gender' => $e->student?->gender, - 'payment_status' => $e->invoice?->status ?? 'NONE', + 'payment_status' => $e->invoice->status ?? 'NONE', 'academic_status' => $e->academic_status ?? 'en_cours', 'status_reason' => $e->status_reason, ])->values(); diff --git a/app/Http/Controllers/Eleves/StudentController.php b/app/Http/Controllers/Eleves/StudentController.php index 555f6b5..f7893be 100644 --- a/app/Http/Controllers/Eleves/StudentController.php +++ b/app/Http/Controllers/Eleves/StudentController.php @@ -219,7 +219,7 @@ public function show(Student $student): Response 'reference_number' => $i->reference_number, 'template_name' => $i->template?->name, 'issued_by' => $i->issuedBy?->name, - 'issued_at' => $i->issued_at?->format('d/m/Y H:i'), + 'issued_at' => $i->issued_at->format('d/m/Y H:i'), ]); // Inscription de l'année active (pour la réaffectation de classe) @@ -244,7 +244,7 @@ public function show(Student $student): Response 'class_id' => $currentEnrollment->class_id, 'class_name' => $currentEnrollment->classroom?->name, 'class_code' => $currentEnrollment->classroom?->code, - 'year' => $activeYear?->year, + 'year' => $activeYear->year, ] : null, 'classrooms' => Classroom::where('active', true)->orderBy('name')->get(['id', 'name', 'code']), 'documents' => $student->documents()->with('uploadedBy:id,firstname,lastname')->latest()->get()->map(fn ($d) => [ @@ -271,13 +271,13 @@ public function changeClass(Request $request, Student $student): RedirectRespons ]); $activeYear = AcademicYear::where('active', true)->first(['id']); - abort_unless($activeYear, 422, 'Aucune année académique active.'); + abort_unless($activeYear !== null, 422, 'Aucune année académique active.'); $enrollment = Enrollment::where('student_id', $student->id) ->where('academic_year_id', $activeYear->id) ->first(); - abort_unless($enrollment, 422, 'Cet élève n\'a pas d\'inscription pour l\'année active.'); + abort_unless($enrollment !== null, 422, 'Cet élève n\'a pas d\'inscription pour l\'année active.'); $enrollment->update(['class_id' => $validated['class_id']]); @@ -305,9 +305,9 @@ public function history(Student $student): Response 'code' => $enrollment->classroom?->code, ], 'academic_year' => $enrollment->academicYear?->year, - 'enrollment_date' => $enrollment->enrollment_date?->format('Y-m-d'), + 'enrollment_date' => $enrollment->enrollment_date->format('Y-m-d'), 'enrollment_code' => $enrollment->enrollment_code, - 'status' => $enrollment->invoice?->status ?? 'NONE', + 'status' => $enrollment->invoice->status ?? 'NONE', 'academic_status' => $enrollment->academic_status ?? 'en_cours', 'academic_status_label' => Enrollment::ACADEMIC_STATUSES[$enrollment->academic_status ?? 'en_cours'] ?? '—', 'status_reason' => $enrollment->status_reason, diff --git a/app/Http/Controllers/Eleves/StudentStatsController.php b/app/Http/Controllers/Eleves/StudentStatsController.php index bf61172..410b632 100644 --- a/app/Http/Controllers/Eleves/StudentStatsController.php +++ b/app/Http/Controllers/Eleves/StudentStatsController.php @@ -8,6 +8,7 @@ use App\Models\Student; use Illuminate\Http\Request; use Illuminate\Support\Carbon; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use Inertia\Inertia; @@ -48,7 +49,8 @@ public function index(Request $request): Response ]; // Répartition par nationalité (top 6, cohorte) - $byNationality = Student::query() + /** @var Collection $natRows */ + $natRows = Student::query() ->whereIn('id', $studentIds) ->select('nationality', DB::raw('COUNT(*) as count')) ->whereNotNull('nationality') @@ -56,8 +58,8 @@ public function index(Request $request): Response ->groupBy('nationality') ->orderByDesc('count') ->limit(6) - ->get() - ->map(fn ($r) => ['label' => $r->nationality, 'count' => (int) $r->count]); + ->get(); + $byNationality = $natRows->map(fn ($r) => ['label' => $r->nationality, 'count' => (int) $r->count]); // Répartition par tranche d'âge (cohorte) $brackets = [ @@ -89,6 +91,7 @@ public function index(Request $request): Response // Sur-âge (retard scolaire) : âge de l'élève >= âge attendu de sa classe + 2. $overAgeThreshold = 2; + /** @var Collection $ageRows */ $ageRows = Enrollment::query() ->join('classes', 'classes.id', '=', 'enrollments.class_id') ->join('students', 'students.id', '=', 'enrollments.student_id') @@ -102,7 +105,8 @@ public function index(Request $request): Response // Effectifs par classe (année sélectionnée, scolarité active), enrichis du // cycle, du sexe et de la capacité pour permettre filtre et empilage côté client. - $byClass = $selectedYearId + /** @var Collection $byClassRows */ + $byClassRows = $selectedYearId ? Enrollment::query() ->join('classes', 'classes.id', '=', 'enrollments.class_id') ->join('students', 'students.id', '=', 'enrollments.student_id') @@ -118,16 +122,16 @@ classes.expected_age AS level, ->orderByRaw('classes.expected_age NULLS LAST') ->orderBy('classes.name') ->get() - ->map(fn ($r) => [ - 'label' => $r->label, - 'cycle' => $this->cycleLabel($r->cycle), - 'capacity' => (int) $r->capacity, - 'level' => $r->level !== null ? (int) $r->level : null, - 'count' => (int) $r->total, - 'male' => (int) $r->male, - 'female' => (int) $r->female, - ]) : collect(); + $byClass = $byClassRows->map(fn ($r) => [ + 'label' => $r->label, + 'cycle' => $this->cycleLabel($r->cycle), + 'capacity' => (int) $r->capacity, + 'level' => $r->level !== null ? (int) $r->level : null, + 'count' => (int) $r->total, + 'male' => (int) $r->male, + 'female' => (int) $r->female, + ]); return Inertia::render('Eleves/Students/Stats', [ 'summary' => [ diff --git a/app/Http/Controllers/Eleves/TimetableController.php b/app/Http/Controllers/Eleves/TimetableController.php index a0802eb..df4b6e7 100644 --- a/app/Http/Controllers/Eleves/TimetableController.php +++ b/app/Http/Controllers/Eleves/TimetableController.php @@ -125,7 +125,7 @@ public function teacherExport(Request $request) return $this->schedulePdf( $this->teacherSlots($teacher->id, $activeYearId), title: 'EMPLOI DU TEMPS — ENSEIGNANT', - subtitle: $teacher->name.' — Année : '.($year?->year ?? '—'), + subtitle: $teacher->name.' — Année : '.($year->year ?? '—'), filename: 'emploi-du-temps-'.Str::slug($teacher->name), ); } @@ -211,15 +211,19 @@ private function teacherSlots(string $teacherId, ?string $yearId): Collection */ private function buildScheduleGrid(Collection $slots): array { - $range = fn ($s) => substr($s->start_time, 0, 5).'-'.substr($s->end_time, 0, 5); + $range = fn (TimetableSlot $s): string => substr($s->start_time, 0, 5).'-'.substr($s->end_time, 0, 5); + /** @var array> $grid */ $grid = []; foreach ($slots as $slot) { $grid[$range($slot)][$slot->day_of_week] = $slot; } + /** @var Collection $timeRanges */ + $timeRanges = $slots->map($range)->unique()->sort()->values(); + return [ - 'timeRanges' => $slots->map($range)->unique()->sort()->values(), + 'timeRanges' => $timeRanges, 'grid' => $grid, ]; } diff --git a/app/Http/Controllers/Examens/MarkController.php b/app/Http/Controllers/Examens/MarkController.php index 43ff238..900a57e 100644 --- a/app/Http/Controllers/Examens/MarkController.php +++ b/app/Http/Controllers/Examens/MarkController.php @@ -61,7 +61,7 @@ public function index(Evaluation $evaluation): Response 'student' => $enrollment->student, 'mark_id' => $mark?->id, 'score' => $mark?->score !== null ? (float) $mark->score : null, - 'absent' => $mark?->absent ?? false, + 'absent' => $mark->absent ?? false, 'comments' => $mark?->comments, ]; })->values(); @@ -97,7 +97,7 @@ public function store(Request $request, Evaluation $evaluation) return back()->withErrors(['locked' => $decision->message()]); } - $maxScore = (float) ($evaluation->template?->max_score ?? 20); + $maxScore = (float) ($evaluation->template->max_score ?? 20); // L'élève noté doit être inscrit (activement) dans la classe de l'évaluation : // `exists:students,id` seul laisserait noter un élève d'une autre classe. diff --git a/app/Http/Controllers/Examens/OfficialExamController.php b/app/Http/Controllers/Examens/OfficialExamController.php index 33400cd..7507d45 100644 --- a/app/Http/Controllers/Examens/OfficialExamController.php +++ b/app/Http/Controllers/Examens/OfficialExamController.php @@ -26,7 +26,7 @@ public function index(Request $request): Response $years = AcademicYear::orderByDesc('start_date')->get(['id', 'year', 'active']); // Année par défaut = année académique active - $yearId = $request->string('academic_year_id')->toString() ?: ($activeYear?->id ?? ''); + $yearId = $request->string('academic_year_id')->toString() ?: ($activeYear->id ?? ''); $type = $request->string('type')->toString(); $session = $request->string('session')->toString(); $status = $request->string('status')->toString(); diff --git a/app/Http/Controllers/Notes/NoteReclamationController.php b/app/Http/Controllers/Notes/NoteReclamationController.php index 251c1b4..43db1d8 100644 --- a/app/Http/Controllers/Notes/NoteReclamationController.php +++ b/app/Http/Controllers/Notes/NoteReclamationController.php @@ -55,7 +55,7 @@ public function index(Request $request): Response ]); } - public function create(Request $request): Response + public function create(Request $request): Response|RedirectResponse { abort_unless($request->user()->can('create_note_reclamations'), 403); @@ -152,7 +152,7 @@ public function review(ReviewNoteReclamationRequest $request, NoteReclamation $n $data = $request->validated(); $evaluation = $noteReclamation->evaluation()->with('template:id,max_score')->first(); - $maxScore = (float) ($evaluation?->template?->max_score ?? 9999); + $maxScore = (float) ($evaluation?->template->max_score ?? 9999); if ($data['status'] === 'approved' && isset($data['corrected_score']) && $data['corrected_score'] > $maxScore) { return back()->withErrors(['corrected_score' => "La note corrigée ne peut pas dépasser {$maxScore}."]); diff --git a/app/Http/Controllers/Parametres/BulletinTemplateController.php b/app/Http/Controllers/Parametres/BulletinTemplateController.php index c105df6..024894b 100644 --- a/app/Http/Controllers/Parametres/BulletinTemplateController.php +++ b/app/Http/Controllers/Parametres/BulletinTemplateController.php @@ -21,8 +21,8 @@ public function edit(Request $request): Response $template = BulletinTemplate::where('school_id', $school->id) ->whereNull('classroom_type_id')->first(); - $columns = $template?->columns ?? BulletinTemplate::defaultColumns(); - $options = $template?->options ?? BulletinTemplate::defaultOptions(); + $columns = $template->columns ?? BulletinTemplate::defaultColumns(); + $options = $template->options ?? BulletinTemplate::defaultOptions(); return Inertia::render('Parametres/BulletinTemplates/Edit', [ 'columns' => $columns, @@ -87,7 +87,7 @@ private function presets(): array private function activeSchool(): School { $school = School::query()->first(); - abort_unless($school, 404, 'Aucune école configurée.'); + abort_unless($school !== null, 404, 'Aucune école configurée.'); return $school; } diff --git a/app/Http/Controllers/Parametres/DocumentHeaderController.php b/app/Http/Controllers/Parametres/DocumentHeaderController.php index 040c7a3..57268cd 100644 --- a/app/Http/Controllers/Parametres/DocumentHeaderController.php +++ b/app/Http/Controllers/Parametres/DocumentHeaderController.php @@ -29,7 +29,7 @@ public function edit(Request $request): Response return Inertia::render('Parametres/Documents/HeaderDesigner', [ 'header' => $config, - 'preset' => $header?->preset ?? 'ministeriel', + 'preset' => $header->preset ?? 'ministeriel', 'presets' => DocumentHeader::PRESETS, 'default' => DocumentHeader::defaultLayout($school), 'watermarkImageUrl' => $this->mediaUrl($config['watermark']['image_path'] ?? null), @@ -97,7 +97,7 @@ private function sanitizeLayout(array $layout): array private function activeSchool(): School { $school = School::query()->first(); - abort_unless($school, 404, 'Aucune école configurée.'); + abort_unless($school !== null, 404, 'Aucune école configurée.'); return $school; } diff --git a/app/Http/Controllers/Parametres/DocumentTemplateController.php b/app/Http/Controllers/Parametres/DocumentTemplateController.php index f089a66..33e61a2 100644 --- a/app/Http/Controllers/Parametres/DocumentTemplateController.php +++ b/app/Http/Controllers/Parametres/DocumentTemplateController.php @@ -83,7 +83,7 @@ public function registry(Request $request): Response 'student_name' => $i->student ? $i->student->lastname.' '.$i->student->firstname : '—', 'student_matricule' => $i->student?->matricule, 'issued_by' => $i->issuedBy?->name, - 'issued_at' => $i->issued_at?->format('d/m/Y H:i'), + 'issued_at' => $i->issued_at->format('d/m/Y H:i'), ]); return Inertia::render('Parametres/Documents/Registry', [ diff --git a/app/Http/Controllers/Presences/AttendanceController.php b/app/Http/Controllers/Presences/AttendanceController.php index e128571..3a429a5 100644 --- a/app/Http/Controllers/Presences/AttendanceController.php +++ b/app/Http/Controllers/Presences/AttendanceController.php @@ -77,7 +77,7 @@ public function index(Request $request): Response 'student_id' => $enrollment->student_id, 'student' => $enrollment->student, 'record_id' => $record?->id, - 'status' => $record?->status ?? ($permission ? 'excused' : 'present'), + 'status' => $record->status ?? ($permission ? 'excused' : 'present'), 'minutes_late' => $record?->minutes_late, 'comment' => $record?->comment, 'has_permission' => (bool) $permission, diff --git a/app/Http/Middleware/SetLocale.php b/app/Http/Middleware/SetLocale.php index 128e248..24cf854 100644 --- a/app/Http/Middleware/SetLocale.php +++ b/app/Http/Middleware/SetLocale.php @@ -16,7 +16,7 @@ class SetLocale */ public function handle(Request $request, Closure $next): Response { - $candidate = $request->user()?->locale + $candidate = $request->user()->locale ?? $request->session()->get('locale') ?? config('app.locale'); diff --git a/app/Http/Resources/Api/CalendarEventResource.php b/app/Http/Resources/Api/CalendarEventResource.php index cc3b310..f148d84 100644 --- a/app/Http/Resources/Api/CalendarEventResource.php +++ b/app/Http/Resources/Api/CalendarEventResource.php @@ -2,9 +2,13 @@ namespace App\Http\Resources\Api; +use App\Models\CalendarEvent; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; +/** + * @mixin CalendarEvent + */ class CalendarEventResource extends JsonResource { public function toArray(Request $request): array @@ -13,7 +17,7 @@ public function toArray(Request $request): array 'id' => $this->id, 'title' => $this->title, 'type' => $this->type, - 'start_date' => $this->start_date?->format('Y-m-d'), + 'start_date' => $this->start_date->format('Y-m-d'), 'end_date' => $this->end_date?->format('Y-m-d'), 'all_day' => $this->all_day, 'start_time' => $this->start_time, diff --git a/app/Http/Resources/Api/ReportCardResource.php b/app/Http/Resources/Api/ReportCardResource.php index 72db4cb..0301402 100644 --- a/app/Http/Resources/Api/ReportCardResource.php +++ b/app/Http/Resources/Api/ReportCardResource.php @@ -2,9 +2,13 @@ namespace App\Http\Resources\Api; +use App\Models\ReportCard; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; +/** + * @mixin ReportCard + */ class ReportCardResource extends JsonResource { public function toArray(Request $request): array diff --git a/app/Http/Resources/Api/StudentResource.php b/app/Http/Resources/Api/StudentResource.php index c44af47..74558f1 100644 --- a/app/Http/Resources/Api/StudentResource.php +++ b/app/Http/Resources/Api/StudentResource.php @@ -2,9 +2,13 @@ namespace App\Http\Resources\Api; +use App\Models\Student; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; +/** + * @mixin Student + */ class StudentResource extends JsonResource { public function toArray(Request $request): array diff --git a/app/Models/AbsencePermission.php b/app/Models/AbsencePermission.php index b11fd80..ecd6038 100644 --- a/app/Models/AbsencePermission.php +++ b/app/Models/AbsencePermission.php @@ -32,21 +32,33 @@ class AbsencePermission extends Model 'reviewed_at' => 'datetime', ]; + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function requestedBy(): BelongsTo { return $this->belongsTo(User::class, 'requested_by'); } + /** + * @return BelongsTo + */ public function reviewedBy(): BelongsTo { return $this->belongsTo(User::class, 'reviewed_by'); } + /** + * @return HasMany + */ public function attendanceRecords(): HasMany { return $this->hasMany(AttendanceRecord::class, 'permission_id'); diff --git a/app/Models/AcademicPeriod.php b/app/Models/AcademicPeriod.php index 12bd703..02cacda 100644 --- a/app/Models/AcademicPeriod.php +++ b/app/Models/AcademicPeriod.php @@ -16,12 +16,12 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Support\Collection; class AcademicPeriod extends Model { @@ -49,6 +49,8 @@ class AcademicPeriod extends Model /** * Get the academic year that owns the period. + * + * @return BelongsTo */ public function academicYear(): BelongsTo { @@ -57,6 +59,8 @@ public function academicYear(): BelongsTo /** * Get the class type this period is scoped to (null = toutes les classes). + * + * @return BelongsTo */ public function classType(): BelongsTo { @@ -65,6 +69,8 @@ public function classType(): BelongsTo /** * Get evaluations attached to this academic period. + * + * @return HasMany */ public function evaluations(): HasMany { @@ -75,7 +81,7 @@ public function evaluations(): HasMany * Périodes applicables à un type de classe pour une année donnée. * Priorité aux périodes spécifiques au type ; sinon, périodes globales (class_type_id null). * - * @return Collection + * @return Collection */ public static function forClassType(?string $academicYearId, ?string $classTypeId) { diff --git a/app/Models/AcademicYear.php b/app/Models/AcademicYear.php index dc68093..a1877c3 100644 --- a/app/Models/AcademicYear.php +++ b/app/Models/AcademicYear.php @@ -48,6 +48,8 @@ public function getNameAttribute(): string /** * Get all student scholarships for this academic year. + * + * @return HasMany */ public function studentScholarships(): HasMany { diff --git a/app/Models/AccountingTransaction.php b/app/Models/AccountingTransaction.php index 3d7b9e4..1980a69 100644 --- a/app/Models/AccountingTransaction.php +++ b/app/Models/AccountingTransaction.php @@ -34,11 +34,17 @@ class AccountingTransaction extends Model /* Relations */ /* ------------------------------------------------------------------ */ + /** + * @return BelongsTo + */ public function cashAccount(): BelongsTo { return $this->belongsTo(CashAccount::class); } + /** + * @return BelongsTo + */ public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); diff --git a/app/Models/ArchivedDocument.php b/app/Models/ArchivedDocument.php index 87a079d..c368913 100644 --- a/app/Models/ArchivedDocument.php +++ b/app/Models/ArchivedDocument.php @@ -37,11 +37,17 @@ class ArchivedDocument extends Model 'autre' => 'Autre', ]; + /** + * @return BelongsToMany + */ public function tags(): BelongsToMany { return $this->belongsToMany(DocumentTag::class, 'archived_document_tag'); } + /** + * @return BelongsTo + */ public function archivedBy(): BelongsTo { return $this->belongsTo(User::class, 'archived_by'); diff --git a/app/Models/Attendance.php b/app/Models/Attendance.php index 6c1e744..f57a5ac 100644 --- a/app/Models/Attendance.php +++ b/app/Models/Attendance.php @@ -25,21 +25,33 @@ class Attendance extends Model 'date' => 'date', ]; + /** + * @return BelongsTo + */ public function classroom(): BelongsTo { return $this->belongsTo(Classroom::class, 'class_id'); } + /** + * @return BelongsTo + */ public function academicPeriod(): BelongsTo { return $this->belongsTo(AcademicPeriod::class); } + /** + * @return BelongsTo + */ public function recordedBy(): BelongsTo { return $this->belongsTo(User::class, 'recorded_by'); } + /** + * @return HasMany + */ public function records(): HasMany { return $this->hasMany(AttendanceRecord::class); diff --git a/app/Models/AttendanceRecord.php b/app/Models/AttendanceRecord.php index 6b9a998..c45ba1e 100644 --- a/app/Models/AttendanceRecord.php +++ b/app/Models/AttendanceRecord.php @@ -24,16 +24,25 @@ class AttendanceRecord extends Model 'minutes_late' => 'integer', ]; + /** + * @return BelongsTo + */ public function attendance(): BelongsTo { return $this->belongsTo(Attendance::class); } + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function permission(): BelongsTo { return $this->belongsTo(AbsencePermission::class, 'permission_id'); diff --git a/app/Models/AuditLog.php b/app/Models/AuditLog.php index 23d4059..73c7fce 100644 --- a/app/Models/AuditLog.php +++ b/app/Models/AuditLog.php @@ -31,6 +31,9 @@ class AuditLog extends Model 'new_values' => 'array', ]; + /** + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); diff --git a/app/Models/Backup.php b/app/Models/Backup.php index 213021a..caae059 100644 --- a/app/Models/Backup.php +++ b/app/Models/Backup.php @@ -22,11 +22,17 @@ class Backup extends Model 'includes_media' => 'boolean', ]; + /** + * @return BelongsTo + */ public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } + /** + * @return BelongsTo + */ public function academicYear(): BelongsTo { return $this->belongsTo(AcademicYear::class, 'academic_year_id'); diff --git a/app/Models/BulletinTemplate.php b/app/Models/BulletinTemplate.php index 5d3fc6d..62db6de 100644 --- a/app/Models/BulletinTemplate.php +++ b/app/Models/BulletinTemplate.php @@ -45,11 +45,17 @@ class BulletinTemplate extends Model 'moyenne' => 'Moyenne de période', ]; + /** + * @return BelongsTo + */ public function school(): BelongsTo { return $this->belongsTo(School::class); } + /** + * @return BelongsTo + */ public function classroomType(): BelongsTo { return $this->belongsTo(ClassroomType::class, 'classroom_type_id'); diff --git a/app/Models/CalendarEvent.php b/app/Models/CalendarEvent.php index bb562af..9c5dd8e 100644 --- a/app/Models/CalendarEvent.php +++ b/app/Models/CalendarEvent.php @@ -40,11 +40,17 @@ class CalendarEvent extends Model 'other' => 'Autre', ]; + /** + * @return BelongsTo + */ public function academicYear(): BelongsTo { return $this->belongsTo(AcademicYear::class); } + /** + * @return BelongsTo + */ public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); diff --git a/app/Models/CashAccount.php b/app/Models/CashAccount.php index 757c4e3..1f610ca 100644 --- a/app/Models/CashAccount.php +++ b/app/Models/CashAccount.php @@ -28,11 +28,17 @@ class CashAccount extends Model /* Relations */ /* ------------------------------------------------------------------ */ + /** + * @return HasMany + */ public function transactions(): HasMany { return $this->hasMany(AccountingTransaction::class); } + /** + * @return HasMany + */ public function payments(): HasMany { return $this->hasMany(Payment::class); @@ -44,11 +50,11 @@ public function payments(): HasMany public function typeLabel(): string { + // Colonne enum en base : les trois valeurs couvrent tous les cas. return match ($this->type) { 'CASH' => 'Espèces', 'MOBILE_MONEY' => 'Mobile Money', 'BANK' => 'Banque', - default => $this->type, }; } } diff --git a/app/Models/ClassSubject.php b/app/Models/ClassSubject.php index fd34eeb..c5ad7dc 100644 --- a/app/Models/ClassSubject.php +++ b/app/Models/ClassSubject.php @@ -46,6 +46,8 @@ class ClassSubject extends Model /** * Get the class this assignment belongs to. + * + * @return BelongsTo */ public function class(): BelongsTo { @@ -54,6 +56,8 @@ public function class(): BelongsTo /** * Get the subject for this assignment. + * + * @return BelongsTo */ public function subject(): BelongsTo { @@ -62,6 +66,8 @@ public function subject(): BelongsTo /** * Get the academic year for this class-subject assignment. + * + * @return BelongsTo */ public function academicYear(): BelongsTo { @@ -70,6 +76,8 @@ public function academicYear(): BelongsTo /** * Get all grades for this class-subject combination. + * + * @return HasMany */ public function grades(): HasMany { @@ -78,6 +86,8 @@ public function grades(): HasMany /** * Get all evaluations for this class-subject combination. + * + * @return HasMany */ public function evaluations(): HasMany { diff --git a/app/Models/Classroom.php b/app/Models/Classroom.php index 614d9ef..43d9807 100644 --- a/app/Models/Classroom.php +++ b/app/Models/Classroom.php @@ -45,6 +45,8 @@ class Classroom extends Model /** * Get the classroom type for this classroom. + * + * @return BelongsTo */ public function type(): BelongsTo { @@ -53,6 +55,8 @@ public function type(): BelongsTo /** * Alias for type() relationship. + * + * @return BelongsTo */ public function classroomType(): BelongsTo { @@ -61,6 +65,8 @@ public function classroomType(): BelongsTo /** * Get all attendances for this class. + * + * @return HasMany */ public function attendances(): HasMany { @@ -69,6 +75,8 @@ public function attendances(): HasMany /** * Get all class subjects for this class. + * + * @return HasMany */ public function classSubjects(): HasMany { @@ -77,6 +85,8 @@ public function classSubjects(): HasMany /** * Get all evaluations for this class. + * + * @return HasMany */ public function evaluations(): HasMany { diff --git a/app/Models/ClassroomType.php b/app/Models/ClassroomType.php index efc89cd..0a8c4ab 100644 --- a/app/Models/ClassroomType.php +++ b/app/Models/ClassroomType.php @@ -55,13 +55,19 @@ public function periodsCount(): int /** * Get all classrooms with this type. + * + * @return HasMany */ public function classrooms(): HasMany { return $this->hasMany(Classroom::class, 'classroom_type_id'); } - /** Écoles qui proposent ce type de classe. */ + /** + * Écoles qui proposent ce type de classe. + * + * @return BelongsToMany + */ public function schools(): BelongsToMany { return $this->belongsToMany(School::class, 'class_type_school'); diff --git a/app/Models/DocumentHeader.php b/app/Models/DocumentHeader.php index 53c56c0..7434e8d 100644 --- a/app/Models/DocumentHeader.php +++ b/app/Models/DocumentHeader.php @@ -32,6 +32,9 @@ class DocumentHeader extends Model /** Largeur de référence du canevas = largeur utile d'une page A4 portrait (px @96dpi). */ public const CANVAS_WIDTH = 760; + /** + * @return BelongsTo + */ public function school(): BelongsTo { return $this->belongsTo(School::class); diff --git a/app/Models/DocumentIssuance.php b/app/Models/DocumentIssuance.php index 2393a77..8fb8611 100644 --- a/app/Models/DocumentIssuance.php +++ b/app/Models/DocumentIssuance.php @@ -24,16 +24,25 @@ class DocumentIssuance extends Model 'issued_at' => 'datetime', ]; + /** + * @return BelongsTo + */ public function template(): BelongsTo { return $this->belongsTo(DocumentTemplate::class, 'template_id'); } + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function issuedBy(): BelongsTo { return $this->belongsTo(User::class, 'issued_by'); diff --git a/app/Models/DocumentTag.php b/app/Models/DocumentTag.php index 1efa59b..67cbdd0 100644 --- a/app/Models/DocumentTag.php +++ b/app/Models/DocumentTag.php @@ -13,6 +13,9 @@ class DocumentTag extends Model protected $fillable = ['name', 'slug', 'color']; + /** + * @return BelongsToMany + */ public function documents(): BelongsToMany { return $this->belongsToMany(ArchivedDocument::class, 'archived_document_tag'); diff --git a/app/Models/DocumentTemplate.php b/app/Models/DocumentTemplate.php index fa5e21b..a0854cd 100644 --- a/app/Models/DocumentTemplate.php +++ b/app/Models/DocumentTemplate.php @@ -82,11 +82,17 @@ class DocumentTemplate extends Model ], ]; + /** + * @return BelongsTo + */ public function school(): BelongsTo { return $this->belongsTo(School::class); } + /** + * @return HasMany + */ public function issuances(): HasMany { return $this->hasMany(DocumentIssuance::class, 'template_id'); diff --git a/app/Models/EmployeeAllowance.php b/app/Models/EmployeeAllowance.php index 9f9f9d7..15fbffc 100644 --- a/app/Models/EmployeeAllowance.php +++ b/app/Models/EmployeeAllowance.php @@ -36,11 +36,17 @@ class EmployeeAllowance extends Model 'active' => 'boolean', ]; + /** + * @return BelongsTo + */ public function employeeProfile(): BelongsTo { return $this->belongsTo(EmployeeProfile::class); } + /** + * @return BelongsTo + */ public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); diff --git a/app/Models/EmployeeProfile.php b/app/Models/EmployeeProfile.php index 3fc5011..b55f247 100644 --- a/app/Models/EmployeeProfile.php +++ b/app/Models/EmployeeProfile.php @@ -37,22 +37,35 @@ class EmployeeProfile extends Model 'end_date' => 'date', ]; + /** + * @return BelongsTo + */ public function user(): BelongsTo { return $this->belongsTo(User::class); } + /** + * @return HasMany + */ public function payslips(): HasMany { return $this->hasMany(Payslip::class); } + /** + * @return BelongsTo + */ public function salaryGrade(): BelongsTo { return $this->belongsTo(SalaryGrade::class); } - /** Primes / retenues récurrentes propres à l'employé (tracées). */ + /** + * Primes / retenues récurrentes propres à l'employé (tracées). + * + * @return HasMany + */ public function allowances(): HasMany { return $this->hasMany(EmployeeAllowance::class); @@ -61,7 +74,7 @@ public function allowances(): HasMany /** Nom complet de l'employé (via le compte utilisateur). */ public function fullName(): string { - return trim(($this->user?->firstname ?? '').' '.($this->user?->lastname ?? '')); + return trim(($this->user->firstname ?? '').' '.($this->user->lastname ?? '')); } /** @@ -70,6 +83,6 @@ public function fullName(): string */ public function effectiveBaseSalary(): float { - return (float) ($this->salaryGrade?->base_amount ?? $this->base_salary); + return (float) ($this->salaryGrade->base_amount ?? $this->base_salary); } } diff --git a/app/Models/Enrollment.php b/app/Models/Enrollment.php index ebff4ed..e1450af 100644 --- a/app/Models/Enrollment.php +++ b/app/Models/Enrollment.php @@ -79,31 +79,49 @@ public function scopeActive(Builder $query): Builder /** Statuts considérés comme « scolarité active » (présents à l'appel). */ public const ACTIVE_ACADEMIC_STATUSES = ['en_cours', 'valide', 'non_valide']; + /** + * @return BelongsTo + */ public function school(): BelongsTo { return $this->belongsTo(School::class); } + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function classroom(): BelongsTo { return $this->belongsTo(Classroom::class, 'class_id'); } + /** + * @return BelongsTo + */ public function academicYear(): BelongsTo { return $this->belongsTo(AcademicYear::class, 'academic_year_id'); } + /** + * @return BelongsTo + */ public function enrolledBy(): BelongsTo { return $this->belongsTo(User::class, 'enrolled_by'); } + /** + * @return HasOne + */ public function invoice(): HasOne { return $this->hasOne(Invoice::class); diff --git a/app/Models/Evaluation.php b/app/Models/Evaluation.php index 5e16b4c..173e6fe 100644 --- a/app/Models/Evaluation.php +++ b/app/Models/Evaluation.php @@ -32,16 +32,25 @@ class Evaluation extends Model 'locked_at' => 'datetime', ]; + /** + * @return BelongsTo + */ public function template(): BelongsTo { return $this->belongsTo(EvaluationTemplate::class, 'evaluation_template_id'); } + /** + * @return BelongsTo + */ public function classSubject(): BelongsTo { return $this->belongsTo(ClassSubject::class); } + /** + * @return HasMany + */ public function marks(): HasMany { return $this->hasMany(Mark::class); diff --git a/app/Models/EvaluationTemplate.php b/app/Models/EvaluationTemplate.php index 68bdd95..c8a1209 100644 --- a/app/Models/EvaluationTemplate.php +++ b/app/Models/EvaluationTemplate.php @@ -34,21 +34,33 @@ class EvaluationTemplate extends Model 'date' => 'date', ]; + /** + * @return BelongsTo + */ public function academicPeriod(): BelongsTo { return $this->belongsTo(AcademicPeriod::class); } + /** + * @return BelongsTo + */ public function classType(): BelongsTo { return $this->belongsTo(ClassroomType::class, 'class_type_id'); } + /** + * @return BelongsTo + */ public function evaluationType(): BelongsTo { return $this->belongsTo(EvaluationType::class); } + /** + * @return HasMany + */ public function evaluations(): HasMany { return $this->hasMany(Evaluation::class); diff --git a/app/Models/EvaluationType.php b/app/Models/EvaluationType.php index 1879788..29babde 100644 --- a/app/Models/EvaluationType.php +++ b/app/Models/EvaluationType.php @@ -39,6 +39,8 @@ class EvaluationType extends Model /** * Get all evaluations for this type. + * + * @return HasMany */ public function evaluations(): HasMany { diff --git a/app/Models/FeeStructure.php b/app/Models/FeeStructure.php index 9e6825d..58785a3 100644 --- a/app/Models/FeeStructure.php +++ b/app/Models/FeeStructure.php @@ -20,6 +20,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; class FeeStructure extends Model { @@ -38,6 +39,8 @@ class FeeStructure extends Model /** * Get the academic year that owns the fee structure. + * + * @return BelongsTo */ public function academicYear(): BelongsTo { @@ -46,6 +49,8 @@ public function academicYear(): BelongsTo /** * Get the fee category that owns the fee structure. + * + * @return BelongsTo */ public function feeCategory(): BelongsTo { @@ -54,6 +59,8 @@ public function feeCategory(): BelongsTo /** * Get the classroom that owns the fee structure. + * + * @return BelongsTo */ public function classroom(): BelongsTo { @@ -62,8 +69,10 @@ public function classroom(): BelongsTo /** * Get the installments for the fee structure. + * + * @return HasMany */ - public function installments() + public function installments(): HasMany { return $this->hasMany(Installment::class); } diff --git a/app/Models/Grade.php b/app/Models/Grade.php index 495d88b..89ddc7e 100644 --- a/app/Models/Grade.php +++ b/app/Models/Grade.php @@ -41,6 +41,8 @@ class Grade extends Model /** * Get the student for this grade. + * + * @return BelongsTo */ public function student(): BelongsTo { @@ -49,6 +51,8 @@ public function student(): BelongsTo /** * Get the class subject for this grade. + * + * @return BelongsTo */ public function classSubject(): BelongsTo { @@ -57,6 +61,8 @@ public function classSubject(): BelongsTo /** * Get the academic period for this grade. + * + * @return BelongsTo */ public function academicPeriod(): BelongsTo { diff --git a/app/Models/GradingConfig.php b/app/Models/GradingConfig.php index 6e932ba..36b2209 100644 --- a/app/Models/GradingConfig.php +++ b/app/Models/GradingConfig.php @@ -33,12 +33,19 @@ class GradingConfig extends Model 'mentions' => 'array', ]; + /** + * @return BelongsTo + */ public function school(): BelongsTo { return $this->belongsTo(School::class); } - /** Type de classe ciblé (null = configuration par défaut de l'école). */ + /** + * Type de classe ciblé (null = configuration par défaut de l'école). + * + * @return BelongsTo + */ public function classroomType(): BelongsTo { return $this->belongsTo(ClassroomType::class, 'classroom_type_id'); diff --git a/app/Models/Guardian.php b/app/Models/Guardian.php index b68a76a..c8d8d88 100644 --- a/app/Models/Guardian.php +++ b/app/Models/Guardian.php @@ -34,7 +34,11 @@ class Guardian extends Authenticatable 'password' => 'hashed', ]; - /** Enfants liés à ce tuteur. */ + /** + * Enfants liés à ce tuteur. + * + * @return BelongsToMany + */ public function children(): BelongsToMany { return $this->belongsToMany(Student::class, 'guardian_student')->withPivot('relationship'); diff --git a/app/Models/Installment.php b/app/Models/Installment.php index 1aca32f..096864a 100644 --- a/app/Models/Installment.php +++ b/app/Models/Installment.php @@ -31,16 +31,25 @@ class Installment extends Model /* Relations */ /* ------------------------------------------------------------------ */ + /** + * @return BelongsTo + */ public function feeStructure(): BelongsTo { return $this->belongsTo(FeeStructure::class); } + /** + * @return BelongsTo + */ public function academicPeriod(): BelongsTo { return $this->belongsTo(AcademicPeriod::class); } + /** + * @return HasMany + */ public function payments(): HasMany { return $this->hasMany(Payment::class); diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 6d557b0..4d04c23 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -40,16 +40,25 @@ class Invoice extends Model /* Relations */ /* ------------------------------------------------------------------ */ + /** + * @return BelongsTo + */ public function enrollment(): BelongsTo { return $this->belongsTo(Enrollment::class); } + /** + * @return HasMany + */ public function items(): HasMany { return $this->hasMany(InvoiceItem::class)->orderBy('sort_order'); } + /** + * @return HasMany + */ public function payments(): HasMany { return $this->hasMany(Payment::class)->latest('paid_at'); diff --git a/app/Models/InvoiceItem.php b/app/Models/InvoiceItem.php index 8ae749f..2a99600 100644 --- a/app/Models/InvoiceItem.php +++ b/app/Models/InvoiceItem.php @@ -24,6 +24,9 @@ class InvoiceItem extends Model 'sort_order' => 'integer', ]; + /** + * @return BelongsTo + */ public function invoice(): BelongsTo { return $this->belongsTo(Invoice::class); diff --git a/app/Models/Mark.php b/app/Models/Mark.php index ee3259f..09e5615 100644 --- a/app/Models/Mark.php +++ b/app/Models/Mark.php @@ -30,16 +30,25 @@ class Mark extends Model 'absent' => 'boolean', ]; + /** + * @return BelongsTo + */ public function evaluation(): BelongsTo { return $this->belongsTo(Evaluation::class); } + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); diff --git a/app/Models/NoteReclamation.php b/app/Models/NoteReclamation.php index b40e3ca..426d7f8 100644 --- a/app/Models/NoteReclamation.php +++ b/app/Models/NoteReclamation.php @@ -31,21 +31,33 @@ class NoteReclamation extends Model 'reviewed_at' => 'datetime', ]; + /** + * @return BelongsTo + */ public function evaluation(): BelongsTo { return $this->belongsTo(Evaluation::class); } + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function requestedBy(): BelongsTo { return $this->belongsTo(User::class, 'requested_by'); } + /** + * @return BelongsTo + */ public function reviewedBy(): BelongsTo { return $this->belongsTo(User::class, 'reviewed_by'); diff --git a/app/Models/OfficialExam.php b/app/Models/OfficialExam.php index 48f6d06..1511909 100644 --- a/app/Models/OfficialExam.php +++ b/app/Models/OfficialExam.php @@ -7,6 +7,10 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +/** + * @property-read int|null $registrations_count Agrégat withCount('registrations'). + * @property-read int|null $admis_count Agrégat withCount alias (status = 'admis'). + */ class OfficialExam extends Model { use HasUuids; @@ -37,21 +41,33 @@ class OfficialExam extends Model 'termine' => 'Terminé', ]; + /** + * @return BelongsTo + */ public function school(): BelongsTo { return $this->belongsTo(School::class); } + /** + * @return BelongsTo + */ public function academicYear(): BelongsTo { return $this->belongsTo(AcademicYear::class); } + /** + * @return BelongsTo + */ public function classroom(): BelongsTo { return $this->belongsTo(Classroom::class, 'class_id'); } + /** + * @return HasMany + */ public function registrations(): HasMany { return $this->hasMany(OfficialExamRegistration::class); diff --git a/app/Models/OfficialExamRegistration.php b/app/Models/OfficialExamRegistration.php index 6d54819..e3dd381 100644 --- a/app/Models/OfficialExamRegistration.php +++ b/app/Models/OfficialExamRegistration.php @@ -32,11 +32,17 @@ class OfficialExamRegistration extends Model 'tres_bien' => 'Très bien', ]; + /** + * @return BelongsTo + */ public function officialExam(): BelongsTo { return $this->belongsTo(OfficialExam::class); } + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); diff --git a/app/Models/PayRun.php b/app/Models/PayRun.php index ea61a65..7690824 100644 --- a/app/Models/PayRun.php +++ b/app/Models/PayRun.php @@ -46,16 +46,25 @@ class PayRun extends Model 'paid_at' => 'datetime', ]; + /** + * @return HasMany + */ public function payslips(): HasMany { return $this->hasMany(Payslip::class); } + /** + * @return BelongsTo + */ public function cashAccount(): BelongsTo { return $this->belongsTo(CashAccount::class); } + /** + * @return BelongsTo + */ public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 077c25e..1378478 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -34,31 +34,49 @@ class Payment extends Model /* Relations */ /* ------------------------------------------------------------------ */ + /** + * @return BelongsTo + */ public function invoice(): BelongsTo { return $this->belongsTo(Invoice::class); } + /** + * @return BelongsTo + */ public function installment(): BelongsTo { return $this->belongsTo(Installment::class); } + /** + * @return HasOne + */ public function receipt(): HasOne { return $this->hasOne(Receipt::class); } + /** + * @return BelongsTo + */ public function createdBy(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } + /** + * @return BelongsTo + */ public function cashAccount(): BelongsTo { return $this->belongsTo(CashAccount::class); } + /** + * @return HasOne + */ public function accountingTransaction(): HasOne { return $this->hasOne(AccountingTransaction::class, 'reference_id'); diff --git a/app/Models/Payslip.php b/app/Models/Payslip.php index cc216f8..a21f24e 100644 --- a/app/Models/Payslip.php +++ b/app/Models/Payslip.php @@ -29,11 +29,17 @@ class Payslip extends Model 'payload' => 'array', ]; + /** + * @return BelongsTo + */ public function payRun(): BelongsTo { return $this->belongsTo(PayRun::class); } + /** + * @return BelongsTo + */ public function employeeProfile(): BelongsTo { return $this->belongsTo(EmployeeProfile::class); diff --git a/app/Models/Receipt.php b/app/Models/Receipt.php index 5050f73..a6094a7 100644 --- a/app/Models/Receipt.php +++ b/app/Models/Receipt.php @@ -23,11 +23,17 @@ class Receipt extends Model 'printed_at' => 'datetime', ]; + /** + * @return BelongsTo + */ public function payment(): BelongsTo { return $this->belongsTo(Payment::class); } + /** + * @return BelongsTo + */ public function printedBy(): BelongsTo { return $this->belongsTo(User::class, 'printed_by'); diff --git a/app/Models/ReportCard.php b/app/Models/ReportCard.php index f5d4cc3..1eb8daf 100644 --- a/app/Models/ReportCard.php +++ b/app/Models/ReportCard.php @@ -32,21 +32,33 @@ class ReportCard extends Model 'locked_at' => 'datetime', ]; + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function academicPeriod(): BelongsTo { return $this->belongsTo(AcademicPeriod::class); } + /** + * @return BelongsTo + */ public function classroom(): BelongsTo { return $this->belongsTo(Classroom::class, 'class_id'); } + /** + * @return BelongsTo + */ public function generatedBy(): BelongsTo { return $this->belongsTo(User::class, 'generated_by'); diff --git a/app/Models/SalaryGrade.php b/app/Models/SalaryGrade.php index 0337d8a..12b5a68 100644 --- a/app/Models/SalaryGrade.php +++ b/app/Models/SalaryGrade.php @@ -27,6 +27,9 @@ class SalaryGrade extends Model 'sort_order' => 'integer', ]; + /** + * @return HasMany + */ public function employeeProfiles(): HasMany { return $this->hasMany(EmployeeProfile::class); diff --git a/app/Models/Scholarship.php b/app/Models/Scholarship.php index 86adea6..692e34b 100644 --- a/app/Models/Scholarship.php +++ b/app/Models/Scholarship.php @@ -38,6 +38,8 @@ class Scholarship extends Model /** * Get all student scholarships for this scholarship. + * + * @return HasMany */ public function studentScholarships(): HasMany { diff --git a/app/Models/School.php b/app/Models/School.php index f410b07..39a88fa 100644 --- a/app/Models/School.php +++ b/app/Models/School.php @@ -75,24 +75,37 @@ public function getLogoUrlAttribute(): ?string /** * Get all subjects for the school. + * + * @return HasMany */ public function subjects(): HasMany { return $this->hasMany(Subject::class); } + /** + * @return HasMany + */ public function gradingConfigs(): HasMany { return $this->hasMany(GradingConfig::class); } - /** En-tête personnalisé des documents (certificats, attestations, bulletins). */ + /** + * En-tête personnalisé des documents (certificats, attestations, bulletins). + * + * @return HasOne + */ public function documentHeader(): HasOne { return $this->hasOne(DocumentHeader::class); } - /** Types de classe proposés par l'école. */ + /** + * Types de classe proposés par l'école. + * + * @return BelongsToMany + */ public function classTypes(): BelongsToMany { return $this->belongsToMany(ClassroomType::class, 'class_type_school'); diff --git a/app/Models/Student.php b/app/Models/Student.php index 5a198be..df3cc6c 100644 --- a/app/Models/Student.php +++ b/app/Models/Student.php @@ -28,9 +28,13 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\SoftDeletes; use Laravel\Sanctum\HasApiTokens; +/** + * @property-read Pivot&object{relationship: string} $pivot Pivot guardian_student (chargé via belongsToMany). + */ class Student extends Model implements AuthenticatableContract { use Auditable, AuthenticatableTrait, HasApiTokens, HasFactory, HasResetToken, HasUuids, SoftDeletes; @@ -68,13 +72,18 @@ class Student extends Model implements AuthenticatableContract 'reset_token', ]; - /** Tuteurs liés à cet élève. */ + /** Tuteurs liés à cet élève. * @return BelongsToMany + */ public function guardians(): BelongsToMany { return $this->belongsToMany(Guardian::class, 'guardian_student')->withPivot('relationship'); } - /** Inscriptions de l'élève. */ + /** + * Inscriptions de l'élève. + * + * @return HasMany + */ public function enrollments(): HasMany { return $this->hasMany(Enrollment::class); @@ -82,6 +91,8 @@ public function enrollments(): HasMany /** * Get the user account for this student. + * + * @return BelongsTo */ public function user(): BelongsTo { @@ -90,6 +101,8 @@ public function user(): BelongsTo /** * Get all attendances for this student. + * + * @return HasMany */ public function attendances(): HasMany { @@ -98,6 +111,8 @@ public function attendances(): HasMany /** * Get all grades for this student. + * + * @return HasMany */ public function grades(): HasMany { @@ -106,6 +121,8 @@ public function grades(): HasMany /** * Informations administratives de l'élève. + * + * @return HasOne */ public function information(): HasOne { @@ -114,6 +131,8 @@ public function information(): HasOne /** * Informations parentales de l'élève. + * + * @return HasOne */ public function parentInfo(): HasOne { @@ -122,6 +141,8 @@ public function parentInfo(): HasOne /** * Informations médicales de l'élève. + * + * @return HasOne */ public function medicalInfo(): HasOne { @@ -130,6 +151,8 @@ public function medicalInfo(): HasOne /** * Get all scholarships for this student. + * + * @return HasMany */ public function scholarships(): HasMany { @@ -138,6 +161,8 @@ public function scholarships(): HasMany /** * Get all documents (pièces justificatives) for this student. + * + * @return HasMany */ public function documents(): HasMany { diff --git a/app/Models/StudentDocument.php b/app/Models/StudentDocument.php index 49338d3..4bc5655 100644 --- a/app/Models/StudentDocument.php +++ b/app/Models/StudentDocument.php @@ -24,11 +24,17 @@ class StudentDocument extends Model 'size' => 'integer', ]; + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); } + /** + * @return BelongsTo + */ public function uploadedBy(): BelongsTo { return $this->belongsTo(User::class, 'uploaded_by'); diff --git a/app/Models/StudentInformation.php b/app/Models/StudentInformation.php index 99292eb..a3574b5 100644 --- a/app/Models/StudentInformation.php +++ b/app/Models/StudentInformation.php @@ -39,6 +39,9 @@ class StudentInformation extends Model 'birth_certificate_issue_date' => 'date', ]; + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); diff --git a/app/Models/StudentMedicalInfo.php b/app/Models/StudentMedicalInfo.php index f3fe236..d86e45a 100644 --- a/app/Models/StudentMedicalInfo.php +++ b/app/Models/StudentMedicalInfo.php @@ -34,6 +34,9 @@ class StudentMedicalInfo extends Model 'emergency_contact_phone', ]; + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); diff --git a/app/Models/StudentParent.php b/app/Models/StudentParent.php index da2271d..09b811c 100644 --- a/app/Models/StudentParent.php +++ b/app/Models/StudentParent.php @@ -38,6 +38,9 @@ class StudentParent extends Model 'email', ]; + /** + * @return BelongsTo + */ public function student(): BelongsTo { return $this->belongsTo(Student::class); diff --git a/app/Models/StudentScholarship.php b/app/Models/StudentScholarship.php index 20e74a0..78a8e19 100644 --- a/app/Models/StudentScholarship.php +++ b/app/Models/StudentScholarship.php @@ -28,6 +28,8 @@ class StudentScholarship extends Model /** * Get the student that owns the student scholarship. + * + * @return BelongsTo */ public function student(): BelongsTo { @@ -36,6 +38,8 @@ public function student(): BelongsTo /** * Get the scholarship that owns the student scholarship. + * + * @return BelongsTo */ public function scholarship(): BelongsTo { @@ -44,6 +48,8 @@ public function scholarship(): BelongsTo /** * Get the academic year that owns the student scholarship. + * + * @return BelongsTo */ public function academicYear(): BelongsTo { diff --git a/app/Models/Subject.php b/app/Models/Subject.php index 1fdfb5a..1306ef7 100644 --- a/app/Models/Subject.php +++ b/app/Models/Subject.php @@ -35,19 +35,29 @@ class Subject extends Model /** * Get all class subjects for this subject. + * + * @return HasMany */ public function classSubjects(): HasMany { return $this->hasMany(ClassSubject::class); } - /** Matière parente (si cette matière est une sous-matière). */ + /** + * Matière parente (si cette matière est une sous-matière). + * + * @return BelongsTo + */ public function parent(): BelongsTo { return $this->belongsTo(self::class, 'parent_id'); } - /** Sous-matières. */ + /** + * Sous-matières. + * + * @return HasMany + */ public function children(): HasMany { return $this->hasMany(self::class, 'parent_id'); diff --git a/app/Models/SubjectAssignment.php b/app/Models/SubjectAssignment.php index 55e2e6f..179a491 100644 --- a/app/Models/SubjectAssignment.php +++ b/app/Models/SubjectAssignment.php @@ -40,6 +40,8 @@ class SubjectAssignment extends Model /** * Get the subject for this assignment. + * + * @return BelongsTo */ public function subject(): BelongsTo { @@ -48,6 +50,8 @@ public function subject(): BelongsTo /** * Get the teacher (user) for this assignment. + * + * @return BelongsTo */ public function teacher(): BelongsTo { @@ -56,6 +60,8 @@ public function teacher(): BelongsTo /** * Get the academic year for this assignment. + * + * @return BelongsTo */ public function academicYear(): BelongsTo { @@ -64,6 +70,8 @@ public function academicYear(): BelongsTo /** * Get the class (classroom) for this assignment. + * + * @return BelongsTo */ public function classroom(): BelongsTo { diff --git a/app/Models/TimetableSlot.php b/app/Models/TimetableSlot.php index abb414b..8f9053d 100644 --- a/app/Models/TimetableSlot.php +++ b/app/Models/TimetableSlot.php @@ -28,16 +28,25 @@ class TimetableSlot extends Model 6 => 'Samedi', ]; + /** + * @return BelongsTo + */ public function classroom(): BelongsTo { return $this->belongsTo(Classroom::class, 'class_id'); } + /** + * @return BelongsTo + */ public function subject(): BelongsTo { return $this->belongsTo(Subject::class); } + /** + * @return BelongsTo + */ public function teacher(): BelongsTo { return $this->belongsTo(User::class, 'teacher_id'); diff --git a/app/Models/User.php b/app/Models/User.php index 747b736..b43d312 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -23,6 +23,7 @@ use App\Traits\HasMatricule; use Database\Factories\UserFactory; use Illuminate\Database\Eloquent\Casts\Attribute; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -30,8 +31,12 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Fortify\TwoFactorAuthenticatable; +use Spatie\Permission\Models\Role; use Spatie\Permission\Traits\HasRoles; +/** + * @property-read Collection $roles + */ class User extends Authenticatable { /** @use HasFactory */ @@ -98,27 +103,41 @@ protected function casts(): array /** * Get the user's full name + * + * @return Attribute */ protected function name(): Attribute { return Attribute::make( - get: fn () => "{$this->firstname} {$this->lastname}", + get: fn (): string => "{$this->firstname} {$this->lastname}", ); } - /** Profil RH (paie) de l'utilisateur, s'il est employé. */ + /** + * Profil RH (paie) de l'utilisateur, s'il est employé. + * + * @return HasOne + */ public function employeeProfile(): HasOne { return $this->hasOne(EmployeeProfile::class); } - /** Affectations matières où l'utilisateur est l'enseignant. */ + /** + * Affectations matières où l'utilisateur est l'enseignant. + * + * @return HasMany + */ public function subjectAssignments(): HasMany { return $this->hasMany(SubjectAssignment::class, 'teacher_id'); } - /** Créneaux d'emploi du temps où l'utilisateur est l'enseignant. */ + /** + * Créneaux d'emploi du temps où l'utilisateur est l'enseignant. + * + * @return HasMany + */ public function timetableSlots(): HasMany { return $this->hasMany(TimetableSlot::class, 'teacher_id'); @@ -157,7 +176,7 @@ public function generateMatricule(): string $matriculeService = app(MatriculeService::class); // Obtenir le rôle principal de l'utilisateur - $role = $this->roles?->first()?->name; + $role = $this->roles->first()?->name; if ($role) { return $matriculeService->generateUserMatricule($role); diff --git a/app/Observers/UserObserver.php b/app/Observers/UserObserver.php index 2909403..622c85c 100644 --- a/app/Observers/UserObserver.php +++ b/app/Observers/UserObserver.php @@ -18,7 +18,7 @@ public function created(User $user): void $user->natricule, 'user', $user->id, - $user->roles->first()?->name ?? 'unknown' + $user->roles->first()->name ?? 'unknown' ); } } diff --git a/app/Rules/UniqueMatricule.php b/app/Rules/UniqueMatricule.php index c9c7de9..b186f31 100644 --- a/app/Rules/UniqueMatricule.php +++ b/app/Rules/UniqueMatricule.php @@ -11,9 +11,9 @@ class UniqueMatricule implements ValidationRule { protected MatriculeService $matriculeService; - protected ?int $ignoreId = null; + protected ?string $ignoreId = null; - public function __construct(?int $ignoreId = null) + public function __construct(?string $ignoreId = null) { $this->matriculeService = app(MatriculeService::class); $this->ignoreId = $ignoreId; diff --git a/app/Services/AccountingService.php b/app/Services/AccountingService.php index 31b08ab..fc54177 100644 --- a/app/Services/AccountingService.php +++ b/app/Services/AccountingService.php @@ -112,7 +112,7 @@ public function recordScholarshipTransaction( $studentName = $student ? "{$student->firstname} {$student->lastname}" : 'Élève inconnu'; - $scholarshipName = $scholarship?->name ?? 'Bourse'; + $scholarshipName = $scholarship->name ?? 'Bourse'; return AccountingTransaction::create([ 'type' => 'EXPENSE', diff --git a/app/Services/BackupService.php b/app/Services/BackupService.php index 25f16e8..7f009fe 100644 --- a/app/Services/BackupService.php +++ b/app/Services/BackupService.php @@ -229,6 +229,9 @@ private function addDiskToZip(\ZipArchive $zip, string $diskName, string $prefix $zip->addFile($local, "{$prefix}/{$rel}"); } else { $t = tempnam(sys_get_temp_dir(), 'med_'); + if ($t === false) { + continue; // impossible de créer le fichier temporaire : on saute ce média + } file_put_contents($t, $disk->get($rel)); $temps[] = $t; $zip->addFile($t, "{$prefix}/{$rel}"); @@ -269,7 +272,7 @@ private function writeDump(string $format, string $tmp): string * (json[.gz], sql[.gz] ou dump PostgreSQL). Une sauvegarde de sécurité * (JSON) est générée au préalable. * - * @return array{format:string, tables:int, rows?:int} + * @return array{format:string, tables:int, rows?:int, media?:int} */ public function restore(UploadedFile $file, ?string $onlyTable = null): array { @@ -496,10 +499,8 @@ private function restoreTableBatched(string $table, array $rows): int $total = 0; foreach (array_chunk($rows, 500) as $chunk) { - if (! empty($chunk)) { - DB::transaction(fn () => DB::table($table)->insert($chunk)); - $total += count($chunk); - } + DB::transaction(fn () => DB::table($table)->insert($chunk)); + $total += count($chunk); } return $total; @@ -512,7 +513,7 @@ private function restoreTableBatched(string $table, array $rows): int private function restoreSql(string $contents): array { preg_match_all('/INSERT\s+INTO\s+"([^"]+)"/i', $contents, $matches); - $tables = array_values(array_unique($matches[1] ?? [])); + $tables = array_values(array_unique($matches[1])); try { DB::transaction(function () use ($contents, $tables): void { diff --git a/app/Services/BulletinRenderer.php b/app/Services/BulletinRenderer.php index 0c00f04..7c0ec69 100644 --- a/app/Services/BulletinRenderer.php +++ b/app/Services/BulletinRenderer.php @@ -235,7 +235,7 @@ private function infoBlock(array $p): string private function footBlock(array $p, array $options): string { $average = $this->num($p['average'] ?? null); - $rank = isset($p['rank']) && $p['rank'] !== null ? e($this->ordinal((int) $p['rank'])) : '—'; + $rank = isset($p['rank']) ? e($this->ordinal((int) $p['rank'])) : '—'; $effectif = e((string) ($p['effectif'] ?? '')); $mention = e($p['mention'] ?? '—'); $obs = e($p['observations'] ?? ''); diff --git a/app/Services/DocumentRenderer.php b/app/Services/DocumentRenderer.php index 309a3be..9a9b48b 100644 --- a/app/Services/DocumentRenderer.php +++ b/app/Services/DocumentRenderer.php @@ -90,16 +90,21 @@ public function resolveVariables( ]; if ($student) { + // $student peut être un modèle NON persisté (aperçu/test) : les colonnes + // NOT NULL en base peuvent alors être nulles. On lit via getAttribute() + // (type mixed) pour conserver les gardes défensives. + $birthDate = $student->getAttribute('birth_date'); + $vars += [ 'eleve.nom_complet' => trim(($student->lastname ?? '').' '.($student->firstname ?? '')), 'eleve.nom' => $student->lastname ?? '', 'eleve.prenom' => $student->firstname ?? '', 'eleve.matricule' => $student->matricule ?? '', - 'eleve.date_naissance' => $student->birth_date - ? Carbon::parse($student->birth_date)->locale('fr')->isoFormat('D MMMM YYYY') + 'eleve.date_naissance' => $birthDate + ? Carbon::parse($birthDate)->locale('fr')->isoFormat('D MMMM YYYY') : '', 'eleve.lieu_naissance' => $student->place_of_birth ?? '', - 'eleve.sexe' => match ($student->gender) { + 'eleve.sexe' => match ($student->getAttribute('gender')) { 'male' => 'Masculin', 'female' => 'Féminin', default => '', @@ -198,7 +203,7 @@ public function watermarkHtml(?School $school, array $variables): string protected function renderHeader(DocumentTemplate $template, array $variables): string { $header = $template->school?->documentHeader; - $preset = $header?->preset ?? 'ministeriel'; + $preset = $header->preset ?? 'ministeriel'; // Préréglage « personnalisé » : canevas glisser-déposer (si des éléments existent). // Sinon on rend le gabarit officiel ministériel (défaut). diff --git a/app/Services/GradingService.php b/app/Services/GradingService.php index f546dd3..5590bef 100644 --- a/app/Services/GradingService.php +++ b/app/Services/GradingService.php @@ -424,7 +424,7 @@ public function periodAverageFromEvaluations(string $studentId, string $periodId /** * Attribue des rangs à une liste [{student_id, average}]. * - * @param Collection $rows + * @param Collection $rows * @return Collection */ public function rank(Collection $rows): Collection @@ -469,7 +469,7 @@ private function activeStudentIds(string $classId): Collection /** * Attribue les rangs (1, 1, 3…). Les élèves sans moyenne ne sont pas classés (rang null). * - * @param Collection $rows + * @param Collection $rows * @return Collection */ private function assignRanks(Collection $rows): Collection diff --git a/app/Services/PayrollService.php b/app/Services/PayrollService.php index d2f6b0c..2e7eea7 100644 --- a/app/Services/PayrollService.php +++ b/app/Services/PayrollService.php @@ -137,7 +137,7 @@ private function buildLines(EmployeeProfile $employee, $components, int $month, $grossEarnings = 0.0; foreach ($lines as $l) { if (($l['type'] ?? '') !== SalaryComponent::DEDUCTION) { - $grossEarnings += (float) ($l['amount'] ?? 0); + $grossEarnings += (float) ($l['amount']); } } $statutory = $this->statutory($grossEarnings, $settings); @@ -197,7 +197,7 @@ private function progressiveTax(float $taxable, array $brackets): float $tax = 0.0; $prev = 0.0; foreach ($brackets as $b) { - $cap = isset($b['up_to']) && $b['up_to'] !== null ? (float) $b['up_to'] : INF; + $cap = isset($b['up_to']) ? (float) $b['up_to'] : INF; $rate = (float) ($b['rate'] ?? 0); if ($taxable <= $prev) { break; @@ -382,6 +382,8 @@ private function totals(array $lines): array private function refreshTotals(PayRun $run): void { + // Agrégat sans GROUP BY : toujours une ligne, colonnes calculées. + /** @var object{g: int|float|string, d: int|float|string, n: int|float|string} $sums */ $sums = $run->payslips()->selectRaw(' coalesce(sum(gross), 0) as g, coalesce(sum(total_deductions), 0) as d, diff --git a/app/Services/ReportCardBuilder.php b/app/Services/ReportCardBuilder.php index 555a168..08c9e06 100644 --- a/app/Services/ReportCardBuilder.php +++ b/app/Services/ReportCardBuilder.php @@ -99,7 +99,7 @@ public function build( 'lowest' => $values->isNotEmpty() ? $values->min() : null, 'average' => $values->isNotEmpty() ? round($values->avg(), 2) : null, ]; - $periodSystem = $class->classroomType?->period_system ?? 'trimestre'; + $periodSystem = $class->classroomType->period_system ?? 'trimestre'; $retards = $this->retardsByStudent($class->id, $period); // Récapitulatif inter-périodes + annuel (classements précalculés une fois, depuis l'index). @@ -162,7 +162,7 @@ public function build( } $lines[] = [ - 'subject' => $cs->subject?->name ?? '', + 'subject' => $cs->subject->name ?? '', 'parent' => $cs->subject?->parent?->name, 'group' => $cs->group ?? 'obligatoire', 'coefficient' => $coeff, @@ -171,7 +171,7 @@ public function build( 'moyenne' => $cell['moy'], 'points' => $points, 'definitive' => $points, - 'by_type' => $cell['by_type'] ?? [], + 'by_type' => $cell['by_type'], 'rang' => $subjectRanks[$cs->id]->get($student->id)['rank'] ?? null, 'appreciation' => $comments[$student->id.'|'.$cs->id] ?? '', 'teacher' => $teachers[$cs->subject_id] ?? '', @@ -257,7 +257,7 @@ public function classSubjects(Classroom $class, ?string $yearId): Collection ->with(['subject:id,name,code,parent_id', 'subject.parent:id,name']) ->get() // Regroupe les sous-matières sous leur matière parente. - ->sortBy(fn ($cs) => ($cs->subject?->parent?->name ?? $cs->subject?->name).'~'.($cs->subject?->name)) + ->sortBy(fn ($cs) => ($cs->subject?->parent->name ?? $cs->subject->name).'~'.($cs->subject->name)) ->values(); } @@ -282,7 +282,7 @@ private function teachersBySubject(string $classId, ?string $yearId): array ->when($yearId, fn ($q) => $q->where('academic_year_id', $yearId)) ->with('teacher:id,firstname,lastname') ->get() - ->mapWithKeys(fn ($a) => [$a->subject_id => trim(($a->teacher?->firstname ?? '').' '.($a->teacher?->lastname ?? ''))]) + ->mapWithKeys(fn ($a) => [$a->subject_id => trim(($a->teacher->firstname ?? '').' '.($a->teacher->lastname ?? ''))]) ->toArray(); } diff --git a/app/Services/StatisticsService.php b/app/Services/StatisticsService.php index 9d515c8..353cef0 100644 --- a/app/Services/StatisticsService.php +++ b/app/Services/StatisticsService.php @@ -334,10 +334,10 @@ public function successStats(array $filters): array 'moyenne_generale' => $rcStats->avg_moy !== null ? round((float) $rcStats->avg_moy, 2) : null, 'pass_rate' => $rcTotal > 0 ? round(((int) $rcStats->pass_count) / $rcTotal * 100, 1) : 0.0, 'mentions' => [ - 'passable' => (int) ($mentions['passable'] ?? 0), - 'assez_bien' => (int) ($mentions['assez_bien'] ?? 0), - 'bien' => (int) ($mentions['bien'] ?? 0), - 'tres_bien' => (int) ($mentions['tres_bien'] ?? 0), + 'passable' => (int) ($mentions['passable']), + 'assez_bien' => (int) ($mentions['assez_bien']), + 'bien' => (int) ($mentions['bien']), + 'tres_bien' => (int) ($mentions['tres_bien']), ], 'exams' => $exams, 'exams_summary' => [ @@ -395,6 +395,9 @@ public function attendanceStats(array $filters): array ->sortByDesc('absence_rate') ->values(); + // GROUP BY + HAVING : un ->count() SQL compterait les lignes par groupe, + // pas le nombre de groupes. On matérialise puis on compte en mémoire. + // @phpstan-ignore larastan.noUnnecessaryCollectionCall $chronic = (clone $base) ->where('ar.status', 'absent') ->groupBy('ar.student_id') diff --git a/app/Support/FrenchNumberSpeller.php b/app/Support/FrenchNumberSpeller.php index f0b8079..a883b1e 100644 --- a/app/Support/FrenchNumberSpeller.php +++ b/app/Support/FrenchNumberSpeller.php @@ -138,7 +138,7 @@ private static function tens(int $n, bool $isFinal): string ? ($isFinal ? 'quatre-vingts' : 'quatre-vingt') : 'quatre-vingt-'.self::UNITS[$unit], 90 => 'quatre-vingt-'.self::UNITS[10 + $unit], - default => self::UNITS[$n], // inatteignable, garde-fou + default => throw new \LogicException("Dizaine inattendue: {$base}"), // inatteignable pour n ∈ [20,99] }; } diff --git a/app/Traits/HasMatricule.php b/app/Traits/HasMatricule.php index 0dd83ad..f391445 100644 --- a/app/Traits/HasMatricule.php +++ b/app/Traits/HasMatricule.php @@ -14,9 +14,10 @@ trait HasMatricule */ public static function bootHasMatricule() { - // Générer le matricule avant la création si absent - static::creating(function ($model) { - if (empty($model->natricule) && method_exists($model, 'generateMatricule')) { + // Générer le matricule avant la création si absent. + // Le modèle hôte expose generateMatricule() (cf. User::generateMatricule()). + static::creating(function (self $model) { + if (empty($model->natricule)) { $model->natricule = $model->generateMatricule(); } }); diff --git a/database/migrations/2026_02_16_150000_add_unique_indexes_to_matricules.php b/database/migrations/2026_02_16_150000_add_unique_indexes_to_matricules.php index 60ef1dc..53d5760 100644 --- a/database/migrations/2026_02_16_150000_add_unique_indexes_to_matricules.php +++ b/database/migrations/2026_02_16_150000_add_unique_indexes_to_matricules.php @@ -16,7 +16,7 @@ public function up(): void Schema::table('users', function (Blueprint $table) { // Check if index doesn't already exist if (! Schema::hasIndex('users', 'users_natricule_unique')) { - $table->unique('natricule')->index(); + $table->unique('natricule'); } }); } @@ -25,7 +25,7 @@ public function up(): void if (Schema::hasTable('students') && Schema::hasColumn('students', 'registration_number')) { Schema::table('students', function (Blueprint $table) { if (! Schema::hasIndex('students', 'students_registration_number_unique')) { - $table->unique('registration_number')->index(); + $table->unique('registration_number'); } }); } diff --git a/database/migrations/2026_06_14_000011_add_locked_at_to_evaluations_table.php b/database/migrations/2026_06_14_000011_add_locked_at_to_evaluations_table.php index d8bbe6e..b1000e3 100644 --- a/database/migrations/2026_06_14_000011_add_locked_at_to_evaluations_table.php +++ b/database/migrations/2026_06_14_000011_add_locked_at_to_evaluations_table.php @@ -10,7 +10,7 @@ public function up(): void { Schema::table('evaluations', function (Blueprint $table) { $table->timestamp('locked_at')->nullable()->after('status'); - $table->foreignUuid('locked_by')->nullable()->constrained('users')->nullOnDelete()->after('locked_at'); + $table->foreignUuid('locked_by')->nullable()->after('locked_at')->constrained('users')->nullOnDelete(); }); } diff --git a/database/seeders/DemoSeeder.php b/database/seeders/DemoSeeder.php index f4d851c..8dca323 100644 --- a/database/seeders/DemoSeeder.php +++ b/database/seeders/DemoSeeder.php @@ -251,7 +251,7 @@ private function resolveContext(): bool /** Cycle d'une classe, tel que référencé par self::CURRICULUM. */ private function cycleOf(Classroom $class): string { - $type = Str::lower($class->type?->name ?? ''); + $type = Str::lower($class->type->name ?? ''); return match (true) { str_contains($type, 'primaire'), str_contains($type, 'maternelle') => 'primaire', diff --git a/database/seeders/StudentTestSeeder.php b/database/seeders/StudentTestSeeder.php index b367ac1..a21b9a5 100644 --- a/database/seeders/StudentTestSeeder.php +++ b/database/seeders/StudentTestSeeder.php @@ -54,10 +54,12 @@ public function run(): void $classroomIds = Classroom::query()->pluck('id')->all(); $enrolledBy = User::query()->value('id'); - $canEnroll = $school && $academicYear && $classroomIds !== []; + // $academicYear est toujours résolu (créé au besoin) ; seules l'école et + // les classes peuvent manquer sur une base vide. + $canEnroll = $school && $classroomIds !== []; if (! $canEnroll) { $this->command?->warn( - 'Élèves créés sans inscription : école, année académique active ou classes manquantes.' + 'Élèves créés sans inscription : école ou classes manquantes.' ); } @@ -162,7 +164,7 @@ public function run(): void * Année académique active : on réutilise l'existante, sinon on crée * l'année scolaire courante (développement uniquement). */ - private function resolveAcademicYear(): ?AcademicYear + private function resolveAcademicYear(): AcademicYear { $active = AcademicYear::query()->where('active', true)->first() ?? AcademicYear::query()->latest('start_date')->first(); diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon deleted file mode 100644 index ceedc4a..0000000 --- a/phpstan-baseline.neon +++ /dev/null @@ -1,2059 +0,0 @@ -parameters: - ignoreErrors: - - - message: '#^Access to an undefined property App\\Models\\Student\:\:\$registration_number\.$#' - identifier: property.notFound - count: 2 - path: app/Console/Commands/GenerateStudentMatricule.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$natricule\.$#' - identifier: property.notFound - count: 2 - path: app/Console/Commands/GenerateStudentMatricule.php - - - - message: '#^Call to an undefined method App\\Models\\Student\:\:generateRegistrationNumber\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Console/Commands/GenerateStudentMatricule.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:generateMatricule\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Console/Commands/GenerateStudentMatricule.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Administration/AuditLogController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Administration/AuditLogController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Administration/GuardianController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Administration/GuardianController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$matricule\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Administration/GuardianController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Administration/GuardianController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Administration/SubjectAssignmentController.php - - - - message: '#^Using nullsafe property access "\?\-\>name" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 4 - path: app/Http/Controllers/Administration/SubjectAssignmentController.php - - - - message: '#^Using nullsafe property access "\?\-\>year" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Administration/SubjectAssignmentController.php - - - - message: '#^Instanceof between App\\Models\\User\|null and App\\Models\\Guardian will always evaluate to false\.$#' - identifier: instanceof.alwaysFalse - count: 2 - path: app/Http/Controllers/Api/ApiController.php - - - - message: '#^Instanceof between App\\Models\\User\|null and App\\Models\\Student will always evaluate to false\.$#' - identifier: instanceof.alwaysFalse - count: 2 - path: app/Http/Controllers/Api/ApiController.php - - - - message: '#^Parameter \#1 \$value of function collect contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Api/ApiController.php - - - - message: '#^Call to an undefined method App\\Models\\User\:\:currentAccessToken\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Http/Controllers/Api/V1/AuthController.php - - - - message: '#^Instanceof between App\\Models\\User\|null and App\\Models\\Guardian will always evaluate to false\.$#' - identifier: instanceof.alwaysFalse - count: 1 - path: app/Http/Controllers/Api/V1/AuthController.php - - - - message: '#^Parameter \#1 \$user of method App\\Http\\Controllers\\Api\\V1\\AuthController\:\:profile\(\) expects App\\Models\\Guardian\|App\\Models\\Student, App\\Models\\User\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Api/V1/AuthController.php - - - - message: '#^Instanceof between App\\Models\\User\|null and App\\Models\\Student will always evaluate to false\.$#' - identifier: instanceof.alwaysFalse - count: 1 - path: app/Http/Controllers/Api/V1/ChildrenController.php - - - - message: '#^Parameter \#1 \$value of function collect contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Api/V1/ChildrenController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$classroom_type_id\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Api/V1/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Api/V1/DashboardController.php - - - - message: '#^Parameter \#1 \$class of method App\\Services\\GradingService\:\:classRanking\(\) expects App\\Models\\Classroom, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Api/V1/DashboardController.php - - - - message: '#^Using nullsafe method call on non\-nullable type Carbon\\CarbonImmutable\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Api/V1/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$classroom_type_id\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Api/V1/GradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$comments\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Api/V1/GradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Api/V1/GradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$score\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Api/V1/GradeController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Api/V1/GradeController.php - - - - message: '#^Parameter \#1 \$class of method App\\Services\\GradingService\:\:classRanking\(\) expects App\\Models\\Classroom, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Api/V1/GradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$color\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Archives/ArchiveController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Archives/ArchiveController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 4 - path: app/Http/Controllers/Archives/ArchiveController.php - - - - message: '#^Constant App\\Http\\Controllers\\Archives\\ArchiveController\:\:TYPES is unused\.$#' - identifier: classConstant.unused - count: 1 - path: app/Http/Controllers/Archives/ArchiveController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Archives/ArchiveController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Pagination\\AbstractPaginator\\:\:through\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Archives/ArchiveController.php - - - - message: '#^Using nullsafe method call on non\-nullable type Carbon\\CarbonImmutable\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/CalendarEventController.php - - - - message: '#^Method Illuminate\\Database\\Eloquent\\Builder\\:\:withSum\(\) invoked with 3 parameters, 2 required\.$#' - identifier: arguments.count - count: 1 - path: app/Http/Controllers/Comptabilite/CashAccountController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$amount\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$currency\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$enrollment\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$invoice\.$#' - identifier: property.notFound - count: 4 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$paid_at\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$total\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Parameter \#1 \$invoice of method App\\Services\\InvoiceService\:\:recordPayment\(\) expects App\\Models\\Invoice, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Parameter \#1 \$school of method App\\Http\\Controllers\\Comptabilite\\InvoiceController\:\:officialHeader\(\) expects App\\Models\\School\|null, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Comptabilite/InvoiceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$amount_paid\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$amount_remaining\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$invoice_number\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$matricule\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$status\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$total\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>amount_paid" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>amount_remaining" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>firstname" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>invoice_number" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>lastname" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>matricule" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>name" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>status" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Using nullsafe property access "\?\-\>total" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 2 - path: app/Http/Controllers/Comptabilite/SituationController.php - - - - message: '#^Access to an undefined property App\\Models\\ReportCard\:\:\$avg_general\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$class\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$code\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$enrollment\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$matricule\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 8 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$subject\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Using nullsafe method call on non\-nullable type Carbon\\CarbonImmutable\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 4 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Using nullsafe property access "\?\-\>code" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 2 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Using nullsafe property access "\?\-\>name" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 9 - path: app/Http/Controllers/Dashboard/DashboardController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$billed\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$collected\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$remaining\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$unpaid_amount\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$unpaid_count\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$amount_paid\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$amount_remaining\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$status\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$total\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Parameter \#1 \$school of method App\\Services\\DocumentRenderer\:\:headerHtml\(\) expects App\\Models\\School, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Parameter \#1 \$school of method App\\Services\\DocumentRenderer\:\:resolveVariables\(\) expects App\\Models\\School, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Eleves/EnrollmentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/PromotionController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Eleves/PromotionController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$matricule\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/PromotionController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/PromotionController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$gender\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 3 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$matricule\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$status\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Using nullsafe property access "\?\-\>id" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Using nullsafe property access "\?\-\>status" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Eleves/RosterController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$code\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$created_at\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$mime\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 6 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$original_name\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$size\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$status\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$uploadedBy\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$year\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Parameter \#1 \$boolean of function abort_unless expects bool, App\\Models\\AcademicYear\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Parameter \#1 \$boolean of function abort_unless expects bool, App\\Models\\Enrollment\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Using nullsafe method call on non\-nullable type Carbon\\CarbonImmutable\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 2 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Using nullsafe property access "\?\-\>status" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Using nullsafe property access on non\-nullable type App\\Models\\AcademicYear\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Eleves/StudentController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$birth_date\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$capacity\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$cycle\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$expected_age\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$female\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$label\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$level\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$male\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Enrollment\:\:\$total\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\Student\:\:\$count\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/StudentStatsController.php - - - - message: '#^Access to an undefined property App\\Models\\User\:\:\$name\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Eleves/TimetableController.php - - - - message: '#^Access to an undefined property App\\Models\\User\|Illuminate\\Database\\Eloquent\\Collection\\:\:\$name\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Eleves/TimetableController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Eleves/TimetableController.php - - - - message: '#^Method App\\Http\\Controllers\\Eleves\\TimetableController\:\:buildScheduleGrid\(\) should return array\{timeRanges\: Illuminate\\Support\\Collection\, grid\: array\\>\} but returns array\{timeRanges\: Illuminate\\Support\\Collection\, grid\: array\, App\\Models\\TimetableSlot\>\>\}\.$#' - identifier: return.type - count: 1 - path: app/Http/Controllers/Eleves/TimetableController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/TimetableController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Eleves/TimetableController.php - - - - message: '#^Using nullsafe property access "\?\-\>year" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Eleves/TimetableController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$class_id\.$#' - identifier: property.notFound - count: 3 - path: app/Http/Controllers/Examens/MarkController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$max_score\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/MarkController.php - - - - message: '#^Using nullsafe property access "\?\-\>absent" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Examens/MarkController.php - - - - message: '#^Using nullsafe property access "\?\-\>max_score" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Examens/MarkController.php - - - - message: '#^Access to an undefined property App\\Models\\OfficialExam\:\:\$admis_count\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$average\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$mention\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$registration_number\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$serie\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$status\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$student\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$student_id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Using nullsafe property access "\?\-\>id" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Examens/OfficialExamController.php - - - - message: '#^Parameter \#1 \$rows of method App\\Services\\GradingService\:\:rank\(\) expects Illuminate\\Support\\Collection\, Illuminate\\Support\\Collection\ given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Notes/BulletinController.php - - - - message: '#^Parameter \#2 \$type of static method App\\Models\\GradingConfig\:\:resolveOrDefault\(\) expects App\\Models\\ClassroomType\|null, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Notes/BulletinController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$classroom_type_id\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Notes/GradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$comments\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Notes/GradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$score\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Notes/GradeController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Notes/GradeController.php - - - - message: '#^Parameter \#1 \$class of method App\\Services\\GradingService\:\:classRanking\(\) expects App\\Models\\Classroom, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Notes/GradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$template\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Notes/NoteReclamationController.php - - - - message: '#^Method App\\Http\\Controllers\\Notes\\NoteReclamationController\:\:create\(\) should return Inertia\\Response but returns Illuminate\\Http\\RedirectResponse\.$#' - identifier: return.type - count: 1 - path: app/Http/Controllers/Notes/NoteReclamationController.php - - - - message: '#^Using nullsafe property access "\?\-\>max_score" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Notes/NoteReclamationController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$reference\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Paie/PayslipController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/BackupController.php - - - - message: '#^Offset ''media'' on array\{format\: string, tables\: int, rows\?\: int\} in isset\(\) does not exist\.$#' - identifier: isset.offset - count: 1 - path: app/Http/Controllers/Parametres/BackupController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Parametres/BackupController.php - - - - message: '#^Parameter \#1 \$boolean of function abort_unless expects bool, App\\Models\\School\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Parametres/BulletinTemplateController.php - - - - message: '#^Using nullsafe property access "\?\-\>columns" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Parametres/BulletinTemplateController.php - - - - message: '#^Using nullsafe property access "\?\-\>options" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Parametres/BulletinTemplateController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$academicYear\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/ClassroomController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$coefficient\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/ClassroomController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/ClassroomController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$subject\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/ClassroomController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\<\(int\|string\),Illuminate\\Database\\Eloquent\\Collection\\>\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Parametres/ClassroomController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Parametres/ClassroomController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$layout\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/DocumentHeaderController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$preset\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/DocumentHeaderController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$watermark\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/DocumentHeaderController.php - - - - message: '#^Parameter \#1 \$boolean of function abort_unless expects bool, App\\Models\\School\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Http/Controllers/Parametres/DocumentHeaderController.php - - - - message: '#^Using nullsafe property access "\?\-\>preset" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Parametres/DocumentHeaderController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/DocumentTemplateController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/DocumentTemplateController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$matricule\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/DocumentTemplateController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 2 - path: app/Http/Controllers/Parametres/DocumentTemplateController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Pagination\\AbstractPaginator\\:\:through\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Parametres/DocumentTemplateController.php - - - - message: '#^Parameter \#1 \$school of method App\\Services\\DocumentRenderer\:\:resolveVariables\(\) expects App\\Models\\School, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 2 - path: app/Http/Controllers/Parametres/DocumentTemplateController.php - - - - message: '#^Using nullsafe method call on non\-nullable type Carbon\\CarbonImmutable\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Parametres/DocumentTemplateController.php - - - - message: '#^Access to an undefined property App\\Models\\FeeStructure\:\:\$installments\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Parametres/FeeStructureController.php - - - - message: '#^Relation ''installments'' is not found in App\\Models\\FeeStructure model\.$#' - identifier: larastan.relationExistence - count: 2 - path: app/Http/Controllers/Parametres/FeeStructureController.php - - - - message: '#^Using nullsafe property access "\?\-\>status" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Controllers/Presences/AttendanceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Rh/EmployeeAllowanceController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Rh/SalaryGradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Rh/SalaryGradeController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Database\\Eloquent\\Collection\\:\:map\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Rh/SalaryGradeController.php - - - - message: '#^Parameter \#1 \$callback of method Illuminate\\Support\\Collection\\|string\|null\>\>\:\:sortBy\(\) contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: app/Http/Controllers/Rh/SalaryGradeController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$employee_number\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Rh/UserPayrollController.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Controllers/Rh/UserPayrollController.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:payslips\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Http/Controllers/Rh/UserPayrollController.php - - - - message: '#^Using nullsafe property access "\?\-\>locale" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Http/Middleware/SetLocale.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$all_day\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$end_date\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$end_time\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$start_date\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$start_time\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$title\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\CalendarEventResource\:\:\$type\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/CalendarEventResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\ReportCardResource\:\:\$average\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/ReportCardResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\ReportCardResource\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/ReportCardResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\ReportCardResource\:\:\$locked_at\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/ReportCardResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\ReportCardResource\:\:\$mention\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/ReportCardResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\ReportCardResource\:\:\$rank\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/ReportCardResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\ReportCardResource\:\:\$reference\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/ReportCardResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\StudentResource\:\:\$enrollments\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\StudentResource\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\StudentResource\:\:\$gender\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\StudentResource\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\StudentResource\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\StudentResource\:\:\$matricule\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Access to an undefined property App\\Http\\Resources\\Api\\StudentResource\:\:\$pivot\.$#' - identifier: property.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Call to an undefined method App\\Http\\Resources\\Api\\StudentResource\:\:relationLoaded\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Http/Resources/Api/StudentResource.php - - - - message: '#^Method App\\Models\\AcademicPeriod\:\:forClassType\(\) should return Illuminate\\Support\\Collection\ but returns Illuminate\\Database\\Eloquent\\Collection\\.$#' - identifier: return.type - count: 2 - path: app/Models/AcademicPeriod.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditExcluded\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Models/CalendarEvent.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditableAttributes\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Models/CalendarEvent.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:recordAudit\(\)\.$#' - identifier: method.notFound - count: 3 - path: app/Models/CalendarEvent.php - - - - message: '#^Match arm comparison between ''BANK'' and ''BANK'' is always true\.$#' - identifier: match.alwaysTrue - count: 1 - path: app/Models/CashAccount.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$marks\.$#' - identifier: property.notFound - count: 1 - path: app/Models/ClassSubject.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$template\.$#' - identifier: property.notFound - count: 1 - path: app/Models/ClassSubject.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$base_amount\.$#' - identifier: property.notFound - count: 1 - path: app/Models/EmployeeProfile.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Models/EmployeeProfile.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: app/Models/EmployeeProfile.php - - - - message: '#^Using nullsafe property access "\?\-\>base_amount" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Models/EmployeeProfile.php - - - - message: '#^Using nullsafe property access "\?\-\>firstname" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Models/EmployeeProfile.php - - - - message: '#^Using nullsafe property access "\?\-\>lastname" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Models/EmployeeProfile.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditExcluded\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Models/Enrollment.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditableAttributes\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Models/Enrollment.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:recordAudit\(\)\.$#' - identifier: method.notFound - count: 3 - path: app/Models/Enrollment.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditExcluded\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Models/Grade.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditableAttributes\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Models/Grade.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:recordAudit\(\)\.$#' - identifier: method.notFound - count: 3 - path: app/Models/Grade.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditExcluded\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Models/ReportCard.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditableAttributes\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Models/ReportCard.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:recordAudit\(\)\.$#' - identifier: method.notFound - count: 3 - path: app/Models/ReportCard.php - - - - message: '#^Method App\\Models\\School\:\:activeGradingConfig\(\) should return App\\Models\\GradingConfig\|null but returns Illuminate\\Database\\Eloquent\\Model\|null\.$#' - identifier: return.type - count: 1 - path: app/Models/School.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditExcluded\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Models/Student.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditableAttributes\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Models/Student.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:recordAudit\(\)\.$#' - identifier: method.notFound - count: 3 - path: app/Models/Student.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Models/User.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditExcluded\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Models/User.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:auditableAttributes\(\)\.$#' - identifier: method.notFound - count: 2 - path: app/Models/User.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:recordAudit\(\)\.$#' - identifier: method.notFound - count: 3 - path: app/Models/User.php - - - - message: '#^Cannot access property \$natricule on class\-string\|object\.$#' - identifier: property.nonObject - count: 1 - path: app/Models/User.php - - - - message: '#^Using nullsafe method call on non\-nullable type Illuminate\\Database\\Eloquent\\Collection\\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Models/User.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Observers/UserObserver.php - - - - message: '#^Using nullsafe property access "\?\-\>name" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Observers/UserObserver.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$class_id\.$#' - identifier: property.notFound - count: 1 - path: app/Policies/EvaluationPolicy.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$subject_id\.$#' - identifier: property.notFound - count: 1 - path: app/Policies/EvaluationPolicy.php - - - - message: '#^Result of && is always false\.$#' - identifier: booleanAnd.alwaysFalse - count: 1 - path: app/Rules/UniqueMatricule.php - - - - message: '#^Strict comparison using \=\=\= between string and int\|null will always evaluate to false\.$#' - identifier: identical.alwaysFalse - count: 1 - path: app/Rules/UniqueMatricule.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$enrollment\.$#' - identifier: property.notFound - count: 2 - path: app/Services/AccountingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Services/AccountingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: app/Services/AccountingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Services/AccountingService.php - - - - message: '#^Using nullsafe property access "\?\-\>name" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Services/AccountingService.php - - - - message: '#^Offset 1 on array\{list\, list\\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: app/Services/BackupService.php - - - - message: '#^Parameter &\$temps by\-ref type of method App\\Services\\BackupService\:\:addDiskToZip\(\) expects array\, array\ given\.$#' - identifier: parameterByRef.type - count: 1 - path: app/Services/BackupService.php - - - - message: '#^Variable \$chunk in empty\(\) always exists and is not falsy\.$#' - identifier: empty.variable - count: 1 - path: app/Services/BackupService.php - - - - message: '#^Parameter \#2 \$student of method App\\Services\\DocumentRenderer\:\:resolveVariables\(\) expects App\\Models\\Student\|null, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Services/BulletinRenderer.php - - - - message: '#^Strict comparison using \!\=\= between mixed and null will always evaluate to true\.$#' - identifier: notIdentical.alwaysTrue - count: 1 - path: app/Services/BulletinRenderer.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$documentHeader\.$#' - identifier: property.notFound - count: 1 - path: app/Services/DocumentRenderer.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$watermark\.$#' - identifier: property.notFound - count: 1 - path: app/Services/DocumentRenderer.php - - - - message: '#^Match arm comparison between ''female'' and ''female'' is always true\.$#' - identifier: match.alwaysTrue - count: 1 - path: app/Services/DocumentRenderer.php - - - - message: '#^Parameter \#1 \$school of method App\\Services\\DocumentRenderer\:\:logoDataUri\(\) expects App\\Models\\School\|null, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 2 - path: app/Services/DocumentRenderer.php - - - - message: '#^Parameter \#1 \$school of method App\\Services\\DocumentRenderer\:\:renderWatermark\(\) expects App\\Models\\School\|null, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Services/DocumentRenderer.php - - - - message: '#^Ternary operator condition is always true\.$#' - identifier: ternary.alwaysTrue - count: 1 - path: app/Services/DocumentRenderer.php - - - - message: '#^Using nullsafe property access "\?\-\>preset" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Services/DocumentRenderer.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$absent\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$academic_period_id\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$coefficient\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$evaluationType\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$evaluation_type_id\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$marks\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$max_score\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$score\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$student_id\.$#' - identifier: property.notFound - count: 1 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$template\.$#' - identifier: property.notFound - count: 2 - path: app/Services/GradingService.php - - - - message: '#^Parameter \#1 \$rows of method App\\Services\\GradingService\:\:assignRanks\(\) expects Illuminate\\Support\\Collection\, Illuminate\\Support\\Collection\ given\.$#' - identifier: argument.type - count: 2 - path: app/Services/GradingService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: app/Services/InvoiceService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$type\.$#' - identifier: property.notFound - count: 1 - path: app/Services/InvoiceService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$value\.$#' - identifier: property.notFound - count: 2 - path: app/Services/InvoiceService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$d\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$g\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$label\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$n\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$reason\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$status\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$type\.$#' - identifier: property.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:appliesTo\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:computeAmount\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Parameter \#1 \$payslip of method App\\Services\\AccountingService\:\:cancelPayrollTransaction\(\) expects App\\Models\\Payslip, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 2 - path: app/Services/PayrollService.php - - - - message: '#^Parameter \#1 \$payslip of method App\\Services\\AccountingService\:\:recordPayrollTransaction\(\) expects App\\Models\\Payslip, Illuminate\\Database\\Eloquent\\Model given\.$#' - identifier: argument.type - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Parameter \#1 \$run of method App\\Services\\PayrollService\:\:refreshTotals\(\) expects App\\Models\\PayRun, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Strict comparison using \!\=\= between mixed and null will always evaluate to true\.$#' - identifier: notIdentical.alwaysTrue - count: 1 - path: app/Services/PayrollService.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 3 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$parent\.$#' - identifier: property.notFound - count: 2 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$period_system\.$#' - identifier: property.notFound - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Offset ''by_type'' on array\{classe\: float\|null, compo\: float\|null, moy\: float\|null, by_type\: array\\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Parameter \#1 \$rows of method App\\Services\\GradingService\:\:rank\(\) expects Illuminate\\Support\\Collection\, Illuminate\\Support\\Collection\ given\.$#' - identifier: argument.type - count: 4 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Parameter \#2 \$type of static method App\\Models\\BulletinTemplate\:\:resolveOrDefault\(\) expects App\\Models\\ClassroomType\|null, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Parameter \#2 \$type of static method App\\Models\\GradingConfig\:\:resolveOrDefault\(\) expects App\\Models\\ClassroomType\|null, Illuminate\\Database\\Eloquent\\Model\|null given\.$#' - identifier: argument.type - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Using nullsafe property access "\?\-\>firstname" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Using nullsafe property access "\?\-\>lastname" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Using nullsafe property access "\?\-\>name" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 2 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Using nullsafe property access "\?\-\>period_system" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: app/Services/ReportCardBuilder.php - - - - message: '#^Called ''count'' on Laravel collection, but could have been retrieved as a query\.$#' - identifier: larastan.noUnnecessaryCollectionCall - count: 1 - path: app/Services/StatisticsService.php - - - - message: '#^Offset ''assez_bien'' on array\{passable\: int, assez_bien\: int, bien\: int, tres_bien\: int\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: app/Services/StatisticsService.php - - - - message: '#^Offset ''bien'' on array\{passable\: int, assez_bien\: int, bien\: int, tres_bien\: int\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: app/Services/StatisticsService.php - - - - message: '#^Offset ''passable'' on array\{passable\: int, assez_bien\: int, bien\: int, tres_bien\: int\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: app/Services/StatisticsService.php - - - - message: '#^Offset ''tres_bien'' on array\{passable\: int, assez_bien\: int, bien\: int, tres_bien\: int\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: app/Services/StatisticsService.php - - - - message: '#^Offset int\<20, max\> does not exist on array\{''zéro'', ''un'', ''deux'', ''trois'', ''quatre'', ''cinq'', ''six'', ''sept'', \.\.\.\}\.$#' - identifier: offsetAccess.notFound - count: 1 - path: app/Support/FrenchNumberSpeller.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Schema\\IndexDefinition\:\:index\(\)\.$#' - identifier: method.notFound - count: 2 - path: database/migrations/2026_02_16_150000_add_unique_indexes_to_matricules.php - - - - message: '#^Call to an undefined method Illuminate\\Database\\Schema\\ForeignKeyDefinition\:\:after\(\)\.$#' - identifier: method.notFound - count: 1 - path: database/migrations/2026_06_14_000011_add_locked_at_to_evaluations_table.php - - - - message: '#^Using nullsafe method call on non\-nullable type Illuminate\\Console\\Command\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: database/seeders/DatabaseSeeder.php - - - - message: '#^Using nullsafe method call on non\-nullable type Illuminate\\Console\\Command\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 3 - path: database/seeders/DefaultUsersSeeder.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$firstname\.$#' - identifier: property.notFound - count: 1 - path: database/seeders/DemoSeeder.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$lastname\.$#' - identifier: property.notFound - count: 1 - path: database/seeders/DemoSeeder.php - - - - message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$name\.$#' - identifier: property.notFound - count: 1 - path: database/seeders/DemoSeeder.php - - - - message: '#^Using nullsafe method call on non\-nullable type Illuminate\\Console\\Command\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 8 - path: database/seeders/DemoSeeder.php - - - - message: '#^Using nullsafe property access "\?\-\>name" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: database/seeders/DemoSeeder.php - - - - message: '#^Using nullsafe method call on non\-nullable type Illuminate\\Console\\Command\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: database/seeders/RolesAndPermissionsSeeder.php - - - - message: '#^Method Database\\Seeders\\StudentTestSeeder\:\:resolveAcademicYear\(\) never returns null so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: database/seeders/StudentTestSeeder.php - - - - message: '#^Using nullsafe method call on non\-nullable type Illuminate\\Console\\Command\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 4 - path: database/seeders/StudentTestSeeder.php diff --git a/phpstan.neon b/phpstan.neon index bea8f51..f3da84b 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,5 @@ includes: - vendor/larastan/larastan/extension.neon - - phpstan-baseline.neon parameters: level: 5 @@ -15,5 +14,11 @@ parameters: # viewDirectories: # - resources/views - # Ignore les faux positifs connus liés à la magie Laravel ici si besoin. - ignoreErrors: [] + # Faux positif de framework : Illuminate\Database\Seeder::$command est typé + # non-nul, mais vaut null quand run() est appelé directement (hors `db:seed`), + # ce que font les seeders invoqués programmatiquement et SeederHardeningTest. + # L'accès nullsafe `$this->command?->` est donc volontaire et correct. + ignoreErrors: + - + message: '#Using nullsafe method call on non-nullable type Illuminate\\Console\\Command\. Use -> instead\.#' + path: database/seeders/*.php