0, 'errors' => 0]; $participants = $incentive->participants()->with('user')->get(); foreach ($participants as $participant) { try { $this->recalculateParticipant($participant, $force); $stats['participants']++; } catch (\Throwable $e) { $stats['errors']++; Log::error('IncentiveCalculation error for participant '.$participant->id.': '.$e->getMessage()); } } IncentiveTracker::updateRanking($incentive); return $stats; } /** * Recalculate a single participant. * Force: Kompletter Neuaufbau aus Quelldaten. * Normal: Neuberechnung aus vorhandenen Tracking-Tabellen + Log. */ public function recalculateParticipant(IncentiveParticipant $participant, bool $force = false): void { if (! $participant->user) { return; } if ($force) { $participant->rebuildFromSourceTables()->save(); } else { $participant->recalculateFromTrackingTables()->save(); } } }