'hms-'.uniqid('', true).'@example.com', 'password' => bcrypt('secret'), 'lang' => 'de', 'm_level' => 1, 'm_sponsor' => $sponsorId, 'active_date' => '2026-01-10', 'payment_account' => $paymentAccount === 'future' ? now()->addYear() : $paymentAccount, ]); } function hmsMonthlyStats(User $user): array { Request::merge(['stats_month' => 8, 'stats_year' => 2026]); $method = (new ReflectionClass(HomeController::class))->getMethod('buildMonthlyStats'); $method->setAccessible(true); return $method->invoke(new HomeController, $user); } it('zaehlt in der Firstlines-Kachel nur aktive Berater, konsistent zu "Teampartner gesamt"', function (): void { $root = hmsMakeUser(); hmsMakeUser($root->id); hmsMakeUser($root->id); // Abgelaufenes, aber gesetztes Abrechnungskonto: zaehlt wie in der // "Berater"-Spalte weiterhin als Berater (BackofficeDashboardService::isActiveConsultant). hmsMakeUser($root->id, now()->subMonth()->toDateString()); // Gar kein Abrechnungskonto: kein Berater hmsMakeUser($root->id, null); $stats = hmsMonthlyStats($root); // Beide Kacheln stehen im selben Cluster und muessen dieselbe Basis nutzen. expect($stats['firstline_count'])->toBe(3) ->and($stats['team_partner_count'])->toBe(3); }); it('zaehlt Neupartner weiterhin ueber alle Firstlines, nicht nur ueber die Kachel-Menge', function (): void { $root = hmsMakeUser(); // Im laufenden Monat aktiv geworden, Konto gueltig -> Neupartner hmsMakeUser($root->id)->forceFill(['active_date' => '2026-08-05'])->save(); // Im laufenden Monat aktiv geworden, Konto abgelaufen -> kein Neupartner, // aber weiterhin Berater in der Firstlines-Kachel hmsMakeUser($root->id, now()->subDay()->toDateString()) ->forceFill(['active_date' => '2026-08-06'])->save(); // Ohne Abrechnungskonto: weder Neupartner noch Berater hmsMakeUser($root->id, null)->forceFill(['active_date' => '2026-08-07'])->save(); $stats = hmsMonthlyStats($root); expect($stats['direct_new_partners'])->toBe(1) ->and($stats['firstline_count'])->toBe(2); });