Changeset View
Changeset View
Standalone View
Standalone View
src/app/Http/Controllers/API/V4/Admin/StatsController.php
Show All 12 Lines | class StatsController extends \App\Http\Controllers\Controller | ||||
public const COLOR_GREEN = '#48d368'; // '#28a745' | public const COLOR_GREEN = '#48d368'; // '#28a745' | ||||
public const COLOR_GREEN_DARK = '#19692c'; | public const COLOR_GREEN_DARK = '#19692c'; | ||||
public const COLOR_RED = '#e77681'; // '#dc3545' | public const COLOR_RED = '#e77681'; // '#dc3545' | ||||
public const COLOR_RED_DARK = '#a71d2a'; | public const COLOR_RED_DARK = '#a71d2a'; | ||||
public const COLOR_BLUE = '#4da3ff'; // '#007bff' | public const COLOR_BLUE = '#4da3ff'; // '#007bff' | ||||
public const COLOR_BLUE_DARK = '#0056b3'; | public const COLOR_BLUE_DARK = '#0056b3'; | ||||
public const COLOR_ORANGE = '#f1a539'; | public const COLOR_ORANGE = '#f1a539'; | ||||
public const TYPE_PAYERS = 1; | |||||
/** @var array List of enabled charts */ | /** @var array List of enabled charts */ | ||||
protected $charts = [ | protected $charts = [ | ||||
'discounts', | 'discounts', | ||||
'income', | 'income', | ||||
'payers', | |||||
'users', | 'users', | ||||
'users-all', | 'users-all', | ||||
'vouchers', | 'vouchers', | ||||
]; | ]; | ||||
/** | /** | ||||
* Fetch chart data | * Fetch chart data | ||||
* | * | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | protected function chartIncome(): array | ||||
'options' => [ 'labelPos' => 'left' ] // default: 'right' | 'options' => [ 'labelPos' => 'left' ] // default: 'right' | ||||
] | ] | ||||
] | ] | ||||
] | ] | ||||
]; | ]; | ||||
} | } | ||||
/** | /** | ||||
* Get payers chart | |||||
*/ | |||||
protected function chartPayers(): array | |||||
{ | |||||
list($labels, $stats) = $this->getCollectedStats(self::TYPE_PAYERS, 54, fn($v) => intval($v)); | |||||
// See https://frappe.io/charts/docs for format/options description | |||||
return [ | |||||
'title' => \trans('app.chart-payers'), | |||||
'type' => 'line', | |||||
'colors' => [self::COLOR_GREEN], | |||||
'axisOptions' => [ | |||||
'xIsSeries' => true, | |||||
'xAxisMode' => 'tick', | |||||
], | |||||
'lineOptions' => [ | |||||
'hideDots' => true, | |||||
'regionFill' => true, | |||||
], | |||||
'data' => [ | |||||
'labels' => $labels, | |||||
'datasets' => [ | |||||
[ | |||||
// 'name' => 'Existing', | |||||
'values' => $stats | |||||
] | |||||
] | |||||
] | |||||
]; | |||||
} | |||||
/** | |||||
* Get created/deleted users chart | * Get created/deleted users chart | ||||
*/ | */ | ||||
protected function chartUsers(): array | protected function chartUsers(): array | ||||
{ | { | ||||
$weeks = 8; | $weeks = 8; | ||||
$start = Carbon::now(); | $start = Carbon::now(); | ||||
$labels = []; | $labels = []; | ||||
▲ Show 20 Lines • Show All 229 Lines • ▼ Show 20 Lines | protected function currency() | ||||
// For resellers return their wallet currency | // For resellers return their wallet currency | ||||
if ($user->role == 'reseller') { | if ($user->role == 'reseller') { | ||||
$currency = $user->wallet()->currency; | $currency = $user->wallet()->currency; | ||||
} | } | ||||
// System currency for others | // System currency for others | ||||
return \config('app.currency'); | return \config('app.currency'); | ||||
} | } | ||||
/** | |||||
* Get collected stats for a specific type/period | |||||
* | |||||
* @param int $type Chart | |||||
* @param int $weeks Number of weeks back from now | |||||
* @param ?callable $itemCallback A callback to execute on every stat item | |||||
* | |||||
* @return array [ labels, stats ] | |||||
*/ | |||||
protected function getCollectedStats(int $type, int $weeks, $itemCallback = null): array | |||||
{ | |||||
$start = Carbon::now(); | |||||
$labels = []; | |||||
while ($weeks > 0) { | |||||
$labels[] = $start->format('Y-W'); | |||||
$weeks--; | |||||
if ($weeks) { | |||||
$start->subWeeks(1); | |||||
} | |||||
} | |||||
$labels = array_reverse($labels); | |||||
$start->startOfWeek(Carbon::MONDAY); | |||||
// Get the stats grouped by tenant and week | |||||
$stats = DB::table('stats') | |||||
->selectRaw("tenant_id, date_format(created_at, '%Y-%v') as period, avg(value) as cnt") | |||||
->where('type', $type) | |||||
->where('created_at', '>=', $start->toDateString()) | |||||
->groupByRaw('1,2'); | |||||
// Get the query result and sum up per-tenant stats | |||||
$result = []; | |||||
$this->applyTenantScope($stats)->get() | |||||
->each(function ($item) use (&$result) { | |||||
$result[$item->period] = ($result[$item->period] ?? 0) + $item->cnt; | |||||
}); | |||||
// Process the result, e.g. convert values to int | |||||
if ($itemCallback) { | |||||
$result = array_map($itemCallback, $result); | |||||
} | |||||
// Fill the missing weeks with zeros | |||||
$result = array_values(array_merge(array_fill_keys($labels, 0), $result)); | |||||
return [$labels, $result]; | |||||
} | |||||
} | } |