Payline (A07): Home-Kacheln und Prognose zaehlen die Mitglieder des Provisionsbaums

paylineContext() nahm die gesamte Downline, lineByUserId() und die
Team-Statistik den Provisionsbaum. "Teampartner/Abos in der Payline" und
die Payline-Prognose zaehlten damit auch Berater ohne Mitgliedsebene oder
Abrechnungskonto samt ihrem Unterbaum, deren Abo-Punkte nie in die
Provision eingehen. An der Live-Kopie betrifft das 102 von 162 Beratern
mit Payline. Nach dem Deploy cache:clear (payline_context_*, 6 h).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-09-23 15:44:24 +00:00
parent 1885402a6c
commit 6cd00a60ec
2 changed files with 33 additions and 1 deletions

View file

@ -590,7 +590,9 @@ class PaylineForecastService
return [['paylines' => 0, 'member_ids' => [], 'is_career_fallback' => false], $failed];
}
$memberIds = collect($this->dashboardService->lineBuckets($user->id))
// Mitglieder aus dem Provisionsbaum, wie lineByUserId() und die Team-Statistik
// (Audit A07): Wer dort ausgefiltert oder gekappt ist, zaehlt fuer die Payline nicht.
$memberIds = collect($this->dashboardService->commissionLineBuckets($user->id, $month, $year))
->filter(fn ($users, int $line) => $line <= $paylines)
->flatMap(fn ($users) => $users->pluck('id'))
->map(fn ($id) => (int) $id)

View file

@ -312,6 +312,36 @@ it('ermittelt den Payline-Kontext aus dem UserBusiness-Level und den Linien', fu
->and($context['member_ids'])->not->toContain($ben->id);
});
it('nimmt die Payline-Mitglieder aus dem Provisionsbaum wie die Team-Statistik (A07)', function (): void {
$root = pflMakeUser();
$anna = pflMakeUser($root->id); // Linie 1, im Provisionsbaum
$carl = pflMakeUser($root->id); // Linie 1, ohne Abrechnungskonto
$carl->forceFill(['payment_account' => null])->save();
$dora = pflMakeUser($carl->id); // Linie 2 unter Carl: gekappt
$emil = pflMakeUser($anna->id); // Linie 2 unter Anna: zaehlt
UserBusiness::forceCreate([
'user_id' => $root->id,
'month' => 7,
'year' => 2026,
'version' => 1,
'qual_user_level' => ['paylines' => 2],
]);
pflMakeAbo($dora->id, 'me', '2026-07-20', 50);
pflMakeAbo($emil->id, 'me', '2026-07-20', 30);
$service = app(PaylineForecastService::class);
$context = $service->paylineContext($root, 7, 2026);
$turnover = $service->aboTurnover($root, 7, 2026);
expect($context['member_ids'])->toEqualCanonicalizing([$anna->id, $emil->id])
->and($context['member_ids'])->not->toContain($carl->id)
->and($context['member_ids'])->not->toContain($dora->id)
->and($turnover['team_abo_count'])->toBe(1)
->and($turnover['target'])->toBe(30.0);
});
it('rendert die Payline-Prognose auf der Monatsstatistik-Card', function (): void {
URL::resolveMissingNamedRoutesUsing(fn (string $name, $parameters = []) => '/'.$name);