273 lines
12 KiB
PHP
273 lines
12 KiB
PHP
@php
|
|
$selectedMonth = request()->get('stats_month', date('n'));
|
|
$selectedYear = request()->get('stats_year', date('Y'));
|
|
|
|
// Start- und Enddatum für den Monat
|
|
$startDate = \Carbon\Carbon::createFromDate($selectedYear, $selectedMonth, 1)->startOfMonth();
|
|
$endDate = \Carbon\Carbon::createFromDate($selectedYear, $selectedMonth, 1)->endOfMonth();
|
|
|
|
// UserBusiness für den Monat laden (enthält Payline-Punkte)
|
|
$userBusiness = \App\Models\UserBusiness::where('user_id', $user->id)
|
|
->where('month', $selectedMonth)
|
|
->where('year', $selectedYear)
|
|
->first();
|
|
|
|
// UserSalesVolume für KP-Punkte
|
|
$userSalesVolume = $user->getUserSalesVolume($selectedMonth, $selectedYear, 'first');
|
|
|
|
// Kunden-Umsatz Punkte (KP - Eigene Punkte + Shop)
|
|
$customerPoints = $userSalesVolume ? $userSalesVolume->getPointsKPSum() : 0;
|
|
|
|
// Team-Umsatz Punkte (Payline) - Live-Berechnung wenn UserBusiness nicht verfügbar
|
|
$teamPaylinePoints = 0;
|
|
$isLiveCalculation = false;
|
|
|
|
if ($userBusiness) {
|
|
// Gespeicherte Daten aus UserBusiness verwenden
|
|
$teamPaylinePoints = $userBusiness->payline_points ?? 0;
|
|
} else {
|
|
// Live-Berechnung über TreeCalcBot (für aktuellen Monat)
|
|
$isLiveCalculation = true;
|
|
try {
|
|
$treeCalcBot = new \App\Services\BusinessPlan\TreeCalcBot(
|
|
(int) $selectedMonth,
|
|
(int) $selectedYear,
|
|
'member',
|
|
);
|
|
$treeCalcBot->initBusinesslUserDetail($user);
|
|
|
|
if ($treeCalcBot->business_user) {
|
|
$teamPaylinePoints = $treeCalcBot->business_user->payline_points ?? 0;
|
|
}
|
|
} catch (\Exception $e) {
|
|
\Log::warning("Live-Berechnung Payline-Punkte fehlgeschlagen für User {$user->id}: " . $e->getMessage());
|
|
$teamPaylinePoints = 0;
|
|
}
|
|
}
|
|
|
|
// Direkte Neupartner (Firstlines) in diesem Monat
|
|
$directNewPartners = \App\User::where('m_sponsor', $user->id)
|
|
->whereColumn('id', '!=', 'm_sponsor')
|
|
->where('active_date', '>=', $startDate)
|
|
->where('active_date', '<=', $endDate)
|
|
->where('m_level', '!=', null)
|
|
->where('payment_account', '!=', null)
|
|
->count();
|
|
|
|
// ===== REKURSIVE TEAM-STRUKTUR =====
|
|
// Hilfsfunktion um alle Team-Mitglieder rekursiv zu sammeln (inkl. Sponsor-Kette)
|
|
$getAllTeamMemberIds = function ($sponsorId, $maxDepth = 20) use (&$getAllTeamMemberIds) {
|
|
static $cache = [];
|
|
|
|
if (isset($cache[$sponsorId])) {
|
|
return $cache[$sponsorId];
|
|
}
|
|
|
|
$teamIds = [];
|
|
$currentLevel = [$sponsorId];
|
|
$depth = 0;
|
|
|
|
while (!empty($currentLevel) && $depth < $maxDepth) {
|
|
$children = \App\User::whereIn('m_sponsor', $currentLevel)
|
|
->whereColumn('id', '!=', 'm_sponsor')
|
|
->where('m_level', '!=', null)
|
|
->where('payment_account', '!=', null)
|
|
->whereNull('deleted_at')
|
|
->pluck('id')
|
|
->toArray();
|
|
|
|
$teamIds = array_merge($teamIds, $children);
|
|
$currentLevel = $children;
|
|
$depth++;
|
|
}
|
|
|
|
$cache[$sponsorId] = $teamIds;
|
|
return $teamIds;
|
|
};
|
|
|
|
// Alle Team-Mitglieder rekursiv laden
|
|
$allTeamMemberIds = $getAllTeamMemberIds($user->id);
|
|
|
|
// Neupartner im gesamten Team (rekursiv im Marketingplan)
|
|
$teamNewPartners = 0;
|
|
if (!empty($allTeamMemberIds)) {
|
|
$teamNewPartners = \App\User::whereIn('id', $allTeamMemberIds)
|
|
->where('active_date', '>=', $startDate)
|
|
->where('active_date', '<=', $endDate)
|
|
->count();
|
|
}
|
|
|
|
// Kundenabos (is_for = 'customer' oder shop-bezogen)
|
|
$customerAbos = \App\Models\UserAbo::where('member_id', $user->id)
|
|
->where('is_for', 'ot')
|
|
->whereIn('status', [1, 2]) // aktive Abos
|
|
->where('active', true)
|
|
->count();
|
|
|
|
// Eigene Abos
|
|
$ownAbos = \App\Models\UserAbo::where('user_id', $user->id)
|
|
->where('is_for', 'me')
|
|
->whereIn('status', [1, 2])
|
|
->where('active', true)
|
|
->count();
|
|
|
|
// Team-Abos (rekursiv über gesamtes Team im Marketingplan)
|
|
$teamAbos = 0;
|
|
if (!empty($allTeamMemberIds)) {
|
|
$teamAbos = \App\Models\UserAbo::whereIn('user_id', $allTeamMemberIds)
|
|
->where('is_for', 'me')
|
|
->whereIn('status', [1, 2])
|
|
->where('active', true)
|
|
->count();
|
|
}
|
|
@endphp
|
|
|
|
@if ($user->isActiveAccount())
|
|
<div class="d-flex col-xl-12 align-items-stretch">
|
|
<div class="card w-100 mb-4">
|
|
<h5 class="card-header with-elements d-flex justify-content-between align-items-center flex-wrap">
|
|
<div class="card-header-title">
|
|
<i class="ion ion-md-stats mr-2"></i>{{ __('home.monthly_statistics') }} -
|
|
{{ HTMLHelper::getMonth($selectedMonth) }} {{ $selectedYear }}
|
|
</div>
|
|
<div class="d-flex align-items-center mt-2 mt-md-0">
|
|
<select id="stats-month-filter" class="form-control custom-select form-control-sm mr-2"
|
|
style="width: auto;">
|
|
@foreach (HTMLHelper::getTransMonths() as $monthNum => $monthName)
|
|
<option value="{{ $monthNum }}" {{ $selectedMonth == $monthNum ? 'selected' : '' }}>
|
|
{{ $monthName }}</option>
|
|
@endforeach
|
|
</select>
|
|
<select id="stats-year-filter" class="form-control custom-select form-control-sm"
|
|
style="width: auto;">
|
|
@foreach (HTMLHelper::getYearRange() as $year)
|
|
<option value="{{ $year }}" {{ $selectedYear == $year ? 'selected' : '' }}>
|
|
{{ $year }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
</h5>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
{{-- Kunden-Umsatz Punkte --}}
|
|
<div class="col-md-6 col-lg-4 mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<div class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center"
|
|
style="width: 50px; height: 50px;">
|
|
<i class="ion ion-md-cart" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<div class="text-muted small">{{ __('home.customer_turnover_points') }}</div>
|
|
<div class="font-weight-bold text-large">
|
|
{{ number_format($customerPoints, 0, ',', '.') }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Team-Umsatz Punkte (Payline) --}}
|
|
<div class="col-md-6 col-lg-4 mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<div class="bg-success text-white rounded-circle d-flex align-items-center justify-content-center"
|
|
style="width: 50px; height: 50px;">
|
|
<i class="ion ion-md-people" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<div class="text-muted small">
|
|
{{ __('home.team_turnover_points') }} (Payline)
|
|
@if ($isLiveCalculation)
|
|
<span class="badge badge-pill badge-info ml-1"
|
|
title="{{ __('home.live_calculation_hint') }}">Live</span>
|
|
@endif
|
|
</div>
|
|
<div class="font-weight-bold text-large">
|
|
|
|
{{ number_format($teamPaylinePoints, 0, ',', '.') }}
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
{{-- Direkte Neupartner --}}
|
|
<div class="col-md-6 col-lg-4 mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<div class="bg-info text-white rounded-circle d-flex align-items-center justify-content-center"
|
|
style="width: 50px; height: 50px;">
|
|
<i class="ion ion-md-person-add" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<div class="text-muted small">{{ __('home.direct_new_partners') }}
|
|
</div>
|
|
<div class="font-weight-bold text-large">{{ $directNewPartners }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Neupartner im Team --}}
|
|
<div class="col-md-6 col-lg-4 mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<div class="bg-warning text-white rounded-circle d-flex align-items-center justify-content-center"
|
|
style="width: 50px; height: 50px;">
|
|
<i class="ion ion-md-contacts" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<div class="text-muted small">{{ __('home.team_new_partners') }}</div>
|
|
<div class="font-weight-bold text-large">{{ $teamNewPartners }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Kundenabos --}}
|
|
<div class="col-md-6 col-lg-4 mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<div class="bg-secondary text-white rounded-circle d-flex align-items-center justify-content-center"
|
|
style="width: 50px; height: 50px;">
|
|
<i class="ion ion-md-repeat" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<div class="text-muted small">{{ __('home.customer_subscriptions') }}
|
|
</div>
|
|
<div class="font-weight-bold text-large">{{ $customerAbos }} +
|
|
{{ $ownAbos }}
|
|
{{ __('home.own') }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Team-Abos --}}
|
|
<div class="col-md-6 col-lg-4 mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<div class="bg-dark text-white rounded-circle d-flex align-items-center justify-content-center"
|
|
style="width: 50px; height: 50px;">
|
|
<i class="ion ion-md-sync" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
<div class="ml-3">
|
|
<div class="text-muted small">{{ __('home.team_subscriptions') }}</div>
|
|
<div class="font-weight-bold text-large">{{ $teamAbos }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
// Filter für Monat/Jahr - Statistiken
|
|
function updateStatsFilter() {
|
|
var month = $('#stats-month-filter').val();
|
|
var year = $('#stats-year-filter').val();
|
|
var url = new URL(window.location.href);
|
|
url.searchParams.set('stats_month', month);
|
|
url.searchParams.set('stats_year', year);
|
|
window.location.href = url.toString();
|
|
}
|
|
|
|
$('#stats-month-filter, #stats-year-filter').on('change', function() {
|
|
updateStatsFilter();
|
|
});
|
|
});
|
|
</script>
|
|
@endif
|