Incentive (E1): Recruiting-Challenge mit Geldpraemie, Auszahlungs-Export und parallelen Incentives

Neue Felder amount_per_partner, bonus_rank_1..3 und include_sales_points an
incentives. Mit ausgeschalteten Umsatzpunkten zaehlt die Wertung nur die
Einmalpunkte je Neupartner, die Rangliste entspricht damit der Anzahl
Neupartner mit Starterpaket. IncentivePayoutService rechnet Neupartner mal
Betrag plus Rang-Bonus fuer qualifizierte Gewinner; Admin-Detailseite bekommt
Praemienspalte, Summen und XLSX-Export fuer die Auszahlung.

Sidenav und Dashboard zeigen alle aktiven Incentives, damit Montenegro und
die Challenge parallel laufen koennen. Teaser, Rangliste und Details zeigen
bei Geldpraemie die Praemien-Kachel und "Deine Praemie bisher" und blenden
Abo-Bloecke aus, wenn Abos keine Rolle spielen. Montenegro bleibt unveraendert.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-09-18 12:10:27 +00:00
parent 03416b0afe
commit e3efa2f5f0
27 changed files with 1418 additions and 129 deletions

View file

@ -290,15 +290,15 @@
<div>{{ __('navigation.downloadcenter') }}</div>
</a>
</li>
@php $activeIncentive = \App\Models\Incentive::active()->first(); @endphp
@if ($activeIncentive)
<li class="sidenav-item{{ Request::is('incentive/*') ? ' active' : '' }}">
<a href="{{ route('user_incentive_teaser', [$activeIncentive->slug]) }}"
@php $sidenavIncentives = \App\Models\Incentive::activeForNavigation(); @endphp
@foreach ($sidenavIncentives as $sidenavIncentive)
<li class="sidenav-item{{ Request::is('incentive/' . $sidenavIncentive->slug . '*') ? ' active' : '' }}">
<a href="{{ route('user_incentive_teaser', [$sidenavIncentive->slug]) }}"
class="sidenav-link"><i class="text-secondary sidenav-icon ion ion-md-trophy"></i>
<div>{{ __('navigation.incentive') }}</div>
<div>{{ $sidenavIncentives->count() > 1 ? ($sidenavIncentive->getLang('name') ?: $sidenavIncentive->name) : __('navigation.incentive') }}</div>
</a>
</li>
@endif
@endforeach
@endif
@endif