job_position_id && !$candidate->tenant_id) { $jobPosition = JobPosition::find($candidate->job_position_id); if ($jobPosition) { $candidate->tenant_id = $jobPosition->tenant_id; } } }); } protected $casts = [ 'ai_analysis' => 'array', 'is_selected' => 'boolean', 'interview_details' => 'array', ]; public function jobPosition(): BelongsTo { return $this->belongsTo(JobPosition::class); } protected $appends = ['weighted_score']; public function getWeightedScoreAttribute(): float { $cv = (float)$this->cv_score; $motivation = (float)$this->motivation_score; $interview = (float)$this->interview_score; // On récupère le meilleur test (ramené sur 20) $bestAttempt = $this->attempts()->whereNotNull('finished_at')->get()->map(function($a) { return $a->max_score > 0 ? ($a->score / $a->max_score) * 20 : 0; })->max() ?? 0; $totalPoints = $cv + $motivation + $interview + $bestAttempt; $maxPoints = 20 + 10 + 30 + 20; // Total potentiel = 80 return round(($totalPoints / $maxPoints) * 20, 2); } public function user(): BelongsTo { return $this->belongsTo(User::class); } public function documents(): HasMany { return $this->hasMany(Document::class); } public function attempts(): HasMany { return $this->hasMany(Attempt::class); } }