Backoffice-Statistik: Punkte-Fix (kumulative Snapshots) & Meine Statistik
Punkte/Umsatz korrekt aus per-Zeile points/total_net je status berechnen statt SUM der kumulativen month_*-Snapshots (zaehlte massiv mehrfach). Zentralisiert in SalesVolumePoints, genutzt von Dashboard- & Drilldown-Service. Detail-Tabelle neu gegliedert: Eigenpunkte | Shop | Abo | Sonstige | Kundenpunkte (=Summe) | Gesamt, mit gruener Hervorhebung der Basis-/Summenspalten. Neue VIP-Seite "Meine Statistik" (Untermenue neben Team-Statistik): KPI-Karten + nachvollziehbare Detailtabellen, gruppiert nach eigenen Bestellungen, Shop-Bestellungen und Abos (PersonalStatisticsService). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9565814221
commit
7a620d66ae
14 changed files with 666 additions and 70 deletions
|
|
@ -4,6 +4,7 @@ use App\Http\Controllers\User\BackofficeStatisticsController;
|
|||
use App\Models\ShoppingOrder;
|
||||
use App\Services\Backoffice\BackofficeDashboardService;
|
||||
use App\Services\Backoffice\BackofficeDrilldownService;
|
||||
use App\Services\Backoffice\PersonalStatisticsService;
|
||||
use App\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
|
@ -31,12 +32,13 @@ function makeBackofficeStatisticsRequest(User $user): Request
|
|||
return $request;
|
||||
}
|
||||
|
||||
function makeBackofficeStatisticsController(?BackofficeDashboardService $dashboardService = null, ?BackofficeDrilldownService $drilldownService = null): BackofficeStatisticsController
|
||||
function makeBackofficeStatisticsController(?BackofficeDashboardService $dashboardService = null, ?BackofficeDrilldownService $drilldownService = null, ?PersonalStatisticsService $personalService = null): BackofficeStatisticsController
|
||||
{
|
||||
$dashboardService ??= Mockery::mock(BackofficeDashboardService::class);
|
||||
$drilldownService ??= Mockery::mock(BackofficeDrilldownService::class);
|
||||
$personalService ??= Mockery::mock(PersonalStatisticsService::class);
|
||||
|
||||
return new BackofficeStatisticsController($dashboardService, $drilldownService);
|
||||
return new BackofficeStatisticsController($dashboardService, $drilldownService, $personalService);
|
||||
}
|
||||
|
||||
function backofficeStatisticsStreamedContent(StreamedResponse $response): string
|
||||
|
|
@ -113,6 +115,34 @@ it('blockiert die Backoffice-Statistik fuer normale aktive User', function () {
|
|||
->toThrow(NotFoundHttpException::class);
|
||||
});
|
||||
|
||||
it('blockiert die persoenliche Statistik fuer normale aktive User', function () {
|
||||
$user = makeBackofficeStatisticsUser(0);
|
||||
$controller = makeBackofficeStatisticsController();
|
||||
|
||||
expect(fn () => $controller->my(makeBackofficeStatisticsRequest($user)))
|
||||
->toThrow(NotFoundHttpException::class);
|
||||
});
|
||||
|
||||
it('liefert die persoenliche Statistik fuer VIP-User', function () {
|
||||
$vip = makeBackofficeStatisticsUser(1);
|
||||
$personalService = Mockery::mock(PersonalStatisticsService::class);
|
||||
$personalService
|
||||
->shouldReceive('monthly')
|
||||
->once()
|
||||
->andReturn(['month' => 5, 'year' => 2026, 'totals' => [], 'groups' => []]);
|
||||
|
||||
$controller = makeBackofficeStatisticsController(null, null, $personalService);
|
||||
$request = makeBackofficeStatisticsRequest($vip);
|
||||
$request->query->set('month', 5);
|
||||
$request->query->set('year', 2026);
|
||||
|
||||
$response = $controller->my($request);
|
||||
|
||||
expect($response->name())->toBe('user.backoffice.statistics.my');
|
||||
expect($response->getData()['selectedMonth'])->toBe(5);
|
||||
expect($response->getData()['statistics']['year'])->toBe(2026);
|
||||
});
|
||||
|
||||
it('erstellt einen CSV-Export fuer die Statistik-Uebersicht', function () {
|
||||
$vip = makeBackofficeStatisticsUser(1);
|
||||
$dashboardService = Mockery::mock(BackofficeDashboardService::class);
|
||||
|
|
@ -229,9 +259,9 @@ it('erstellt einen CSV-Export fuer Detaildaten mit Karriere-Level und Summenzeil
|
|||
|
||||
expect($response)->toBeInstanceOf(StreamedResponse::class);
|
||||
expect($response->headers->get('content-disposition'))->toContain('backoffice-statistik-shop_1000-linie-alle-05-2026.csv');
|
||||
expect($content)->toContain('Name;E-Mail;Karriere-Level;Eigenpunkte;"Externe Punkte"');
|
||||
expect($content)->toContain('"Max Mustermann";max@example.test;Partner;400;700;700;0;0;1100');
|
||||
expect($content)->toContain('Summe;"1 Eintraege";;400;700;700;0;0;1100');
|
||||
expect($content)->toContain('Name;E-Mail;Karriere-Level;Eigenpunkte;Shop-Punkte;Abo-Punkte;"Sonstige Punkte";Kundenpunkte;Gesamtpunkte');
|
||||
expect($content)->toContain('"Max Mustermann";max@example.test;Partner;400;0;700;0;700;1100');
|
||||
expect($content)->toContain('Summe;"1 Eintraege";;400;0;700;0;700;1100');
|
||||
});
|
||||
|
||||
it('nutzt den gespeicherten Zeitraum fuer Detailansicht und Export', function () {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue