Recruiting Challenge: Rangliste nach Umsatz der Neupartner, Steuerpflicht
- 50 EUR je Neupartner bleiben; die Top 3 (500/300/200 EUR) ermittelt jetzt der Umsatz der Neupartner (wie Montenegro, ohne Einmalpunkte/Abos) - Gleichstand bei Umsatzwertung: vorn liegt, wessen letzte gezaehlte Umsatzbuchung frueher kam - Challenge-Seite: Praemie und Top-3-Darstellung auch bei Umsatzwertung, Ranglisten-Hinweis auf Umsatz (DE/EN/ES/FR) - Seeder: neue Texte und Bedingungen (Rangliste, Steuerpflicht, vergünstigter Einstieg bis 31.10.), gleicht Wertung beim Einspielen ab Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0a3eb791d4
commit
fe1a9478f4
12 changed files with 239 additions and 79 deletions
|
|
@ -400,6 +400,23 @@ class Incentive extends Model
|
|||
return ! $this->includesSalesPoints() && ! $this->usesAbos() && $this->points_partner_onetime > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rangliste nach Umsatzpunkten der Neupartner: keine Einmal- und keine Abopunkte
|
||||
* (Recruiting-Challenge ab 08.10.2026, Berechnung wie Montenegro).
|
||||
*/
|
||||
public function ranksBySalesOfNewPartners(): bool
|
||||
{
|
||||
return $this->includesSalesPoints() && ! $this->usesAbos() && $this->points_partner_onetime <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Darstellung als Challenge mit Geldpraemie (Praemie je Neupartner, Top-Bonus) statt Punktesystem.
|
||||
*/
|
||||
public function isCashChallenge(): bool
|
||||
{
|
||||
return $this->hasCashPayout() && ($this->ranksByPartnerCount() || $this->ranksBySalesOfNewPartners());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specific translation for a field and locale.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use App\Models\UserAboOrder;
|
|||
use App\Models\UserSalesVolume;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class IncentiveTracker
|
||||
|
|
@ -414,9 +415,37 @@ class IncentiveTracker
|
|||
}
|
||||
}
|
||||
|
||||
if ($incentive->includesSalesPoints()) {
|
||||
foreach (self::latestCountedSalesVolumeAt($participantIds) as $participantId => $timestamp) {
|
||||
$reached[$participantId] = max($reached[$participantId] ?? 0, Carbon::parse($timestamp)->getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
return $reached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Juengste gezaehlte Umsatzbuchung je Teilnehmer, gemessen am Buchungszeitpunkt des
|
||||
* Sales Volumes (bleibt beim Neuaufbau der Logs stabil).
|
||||
*
|
||||
* @param list<int> $participantIds
|
||||
* @return Collection<int, string> Teilnehmer-ID => Zeitstempel
|
||||
*/
|
||||
private static function latestCountedSalesVolumeAt(array $participantIds): Collection
|
||||
{
|
||||
$logTable = (new IncentivePointsLog)->getTable();
|
||||
$volumeTable = (new UserSalesVolume)->getTable();
|
||||
|
||||
return IncentivePointsLog::query()
|
||||
->join($volumeTable, "{$volumeTable}.id", '=', "{$logTable}.user_sales_volume_id")
|
||||
->whereIn("{$logTable}.participant_id", $participantIds)
|
||||
->where("{$logTable}.is_storno", false)
|
||||
->where("{$logTable}.points_accumulated", '>', 0)
|
||||
->groupBy("{$logTable}.participant_id")
|
||||
->selectRaw("{$logTable}.participant_id as participant_id, MAX({$volumeTable}.created_at) as reached_at")
|
||||
->pluck('reached_at', 'participant_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log-Eintrag schreiben (Audit-Trail, keine Duplikate).
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue