Changeset View
Changeset View
Standalone View
Standalone View
src/app/Http/Controllers/API/V4/Admin/StatsController.php
Show All 18 Lines | class StatsController extends \App\Http\Controllers\Controller | ||||
public const COLOR_ORANGE = '#f1a539'; | public const COLOR_ORANGE = '#f1a539'; | ||||
/** @var array List of enabled charts */ | /** @var array List of enabled charts */ | ||||
protected $charts = [ | protected $charts = [ | ||||
'discounts', | 'discounts', | ||||
'income', | 'income', | ||||
'users', | 'users', | ||||
'users-all', | 'users-all', | ||||
'vouchers', | |||||
]; | ]; | ||||
/** | /** | ||||
* Fetch chart data | * Fetch chart data | ||||
* | * | ||||
* @param string $chart Name of the chart | * @param string $chart Name of the chart | ||||
* | * | ||||
* @return \Illuminate\Http\JsonResponse | * @return \Illuminate\Http\JsonResponse | ||||
Show All 40 Lines | protected function chartDiscounts(): array | ||||
// $labels = [10, 25, 30, 100]; | // $labels = [10, 25, 30, 100]; | ||||
// $discounts = [100, 120, 30, 50]; | // $discounts = [100, 120, 30, 50]; | ||||
$labels = array_map(function ($item) { | $labels = array_map(function ($item) { | ||||
return $item . '%'; | return $item . '%'; | ||||
}, $labels); | }, $labels); | ||||
// See https://frappe.io/charts/docs for format/options description | return $this->donutChart(\trans('app.chart-discounts'), $labels, $discounts); | ||||
return [ | |||||
'title' => 'Discounts', | |||||
'type' => 'donut', | |||||
'colors' => [ | |||||
self::COLOR_BLUE, | |||||
self::COLOR_BLUE_DARK, | |||||
self::COLOR_GREEN, | |||||
self::COLOR_GREEN_DARK, | |||||
self::COLOR_ORANGE, | |||||
self::COLOR_RED, | |||||
self::COLOR_RED_DARK | |||||
], | |||||
'maxSlices' => 8, | |||||
'tooltipOptions' => [], // does not work without it (https://github.com/frappe/charts/issues/314) | |||||
'data' => [ | |||||
'labels' => $labels, | |||||
'datasets' => [ | |||||
[ | |||||
'values' => $discounts | |||||
] | |||||
] | |||||
] | |||||
]; | |||||
} | } | ||||
/** | /** | ||||
* Get income chart | * Get income chart | ||||
*/ | */ | ||||
protected function chartIncome(): array | protected function chartIncome(): array | ||||
{ | { | ||||
$weeks = 8; | $weeks = 8; | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | protected function chartIncome(): array | ||||
// $payments = [1000, 1200.25, 3000, 1897.50, 2000, 1900, 2134, 3330]; | // $payments = [1000, 1200.25, 3000, 1897.50, 2000, 1900, 2134, 3330]; | ||||
$avg = collect($payments)->slice(0, count($labels) - 1)->avg(); | $avg = collect($payments)->slice(0, count($labels) - 1)->avg(); | ||||
// See https://frappe.io/charts/docs for format/options description | // See https://frappe.io/charts/docs for format/options description | ||||
return [ | return [ | ||||
'title' => "Income in {$currency} - last 8 weeks", | 'title' => \trans('app.chart-income', ['currency' => $currency]), | ||||
'type' => 'bar', | 'type' => 'bar', | ||||
'colors' => [self::COLOR_BLUE], | 'colors' => [self::COLOR_BLUE], | ||||
'axisOptions' => [ | 'axisOptions' => [ | ||||
'xIsSeries' => true, | 'xIsSeries' => true, | ||||
], | ], | ||||
'data' => [ | 'data' => [ | ||||
'labels' => $labels, | 'labels' => $labels, | ||||
'datasets' => [ | 'datasets' => [ | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | protected function chartUsers(): array | ||||
// $created = [5, 2, 4, 2, 0, 5, 2, 4]; | // $created = [5, 2, 4, 2, 0, 5, 2, 4]; | ||||
// $deleted = [1, 2, 3, 1, 2, 1, 2, 3]; | // $deleted = [1, 2, 3, 1, 2, 1, 2, 3]; | ||||
$avg = collect($created)->slice(0, count($labels) - 1)->avg(); | $avg = collect($created)->slice(0, count($labels) - 1)->avg(); | ||||
// See https://frappe.io/charts/docs for format/options description | // See https://frappe.io/charts/docs for format/options description | ||||
return [ | return [ | ||||
'title' => 'Users - last 8 weeks', | 'title' => \trans('app.chart-users'), | ||||
'type' => 'bar', // Required to fix https://github.com/frappe/charts/issues/294 | 'type' => 'bar', // Required to fix https://github.com/frappe/charts/issues/294 | ||||
'colors' => [self::COLOR_GREEN, self::COLOR_RED], | 'colors' => [self::COLOR_GREEN, self::COLOR_RED], | ||||
'axisOptions' => [ | 'axisOptions' => [ | ||||
'xIsSeries' => true, | 'xIsSeries' => true, | ||||
], | ], | ||||
'data' => [ | 'data' => [ | ||||
'labels' => $labels, | 'labels' => $labels, | ||||
'datasets' => [ | 'datasets' => [ | ||||
[ | [ | ||||
'name' => 'Created', | 'name' => \trans('app.chart-created'), | ||||
'chartType' => 'bar', | 'chartType' => 'bar', | ||||
'values' => $created | 'values' => $created | ||||
], | ], | ||||
[ | [ | ||||
'name' => 'Deleted', | 'name' => \trans('app.chart-deleted'), | ||||
'chartType' => 'line', | 'chartType' => 'line', | ||||
'values' => $deleted | 'values' => $deleted | ||||
] | ] | ||||
], | ], | ||||
'yMarkers' => [ | 'yMarkers' => [ | ||||
[ | [ | ||||
'label' => sprintf('average = %.1f', $avg), | 'label' => sprintf('%s = %.1f', \trans('app.chart-average'), $avg), | ||||
'value' => collect($created)->avg(), | 'value' => collect($created)->avg(), | ||||
'options' => [ 'labelPos' => 'left' ] // default: 'right' | 'options' => [ 'labelPos' => 'left' ] // default: 'right' | ||||
] | ] | ||||
] | ] | ||||
] | ] | ||||
]; | ]; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | protected function chartUsersAll(): array | ||||
// $start = 3000; | // $start = 3000; | ||||
// for ($i = 0; $i < count($labels); $i++) { | // for ($i = 0; $i < count($labels); $i++) { | ||||
// $all[$i] = $start + $i * 15; | // $all[$i] = $start + $i * 15; | ||||
// } | // } | ||||
// See https://frappe.io/charts/docs for format/options description | // See https://frappe.io/charts/docs for format/options description | ||||
return [ | return [ | ||||
'title' => 'All Users - last year', | 'title' => \trans('app.chart-allusers'), | ||||
'type' => 'line', | 'type' => 'line', | ||||
'colors' => [self::COLOR_GREEN], | 'colors' => [self::COLOR_GREEN], | ||||
'axisOptions' => [ | 'axisOptions' => [ | ||||
'xIsSeries' => true, | 'xIsSeries' => true, | ||||
'xAxisMode' => 'tick', | 'xAxisMode' => 'tick', | ||||
], | ], | ||||
'lineOptions' => [ | 'lineOptions' => [ | ||||
'hideDots' => true, | 'hideDots' => true, | ||||
'regionFill' => true, | 'regionFill' => true, | ||||
], | ], | ||||
'data' => [ | 'data' => [ | ||||
'labels' => $labels, | 'labels' => $labels, | ||||
'datasets' => [ | 'datasets' => [ | ||||
[ | [ | ||||
// 'name' => 'Existing', | // 'name' => 'Existing', | ||||
'values' => $all | 'values' => $all | ||||
] | ] | ||||
] | ] | ||||
] | ] | ||||
]; | ]; | ||||
} | } | ||||
/** | /** | ||||
* Get vouchers chart | |||||
*/ | |||||
protected function chartVouchers(): array | |||||
{ | |||||
$vouchers = DB::table('wallets') | |||||
->selectRaw("count(discount_id) as cnt, code") | |||||
->join('discounts', 'discounts.id', '=', 'wallets.discount_id') | |||||
->join('users', 'users.id', '=', 'wallets.user_id') | |||||
->where('discount', '>', 0) | |||||
->whereNotNull('code') | |||||
->whereNull('users.deleted_at') | |||||
->groupBy('discounts.code') | |||||
->havingRaw("count(discount_id) > 0") | |||||
->orderByRaw('1'); | |||||
$addTenantScope = function ($builder, $tenantId) { | |||||
return $builder->where('users.tenant_id', $tenantId); | |||||
}; | |||||
$vouchers = $this->applyTenantScope($vouchers, $addTenantScope) | |||||
->pluck('cnt', 'code')->all(); | |||||
$labels = array_keys($vouchers); | |||||
$vouchers = array_values($vouchers); | |||||
// $labels = ["TEST", "NEW", "OTHER", "US"]; | |||||
// $vouchers = [100, 120, 30, 50]; | |||||
return $this->donutChart(\trans('app.chart-vouchers'), $labels, $vouchers); | |||||
} | |||||
protected static function donutChart($title, $labels, $data): array | |||||
{ | |||||
// See https://frappe.io/charts/docs for format/options description | |||||
return [ | |||||
'title' => $title, | |||||
'type' => 'donut', | |||||
'colors' => [ | |||||
self::COLOR_BLUE, | |||||
self::COLOR_BLUE_DARK, | |||||
self::COLOR_GREEN, | |||||
self::COLOR_GREEN_DARK, | |||||
self::COLOR_ORANGE, | |||||
self::COLOR_RED, | |||||
self::COLOR_RED_DARK | |||||
], | |||||
'maxSlices' => 8, | |||||
'tooltipOptions' => [], // does not work without it (https://github.com/frappe/charts/issues/314) | |||||
'data' => [ | |||||
'labels' => $labels, | |||||
'datasets' => [ | |||||
[ | |||||
'values' => $data | |||||
] | |||||
] | |||||
] | |||||
]; | |||||
} | |||||
/** | |||||
* Add tenant scope to the queries when needed | * Add tenant scope to the queries when needed | ||||
* | * | ||||
* @param \Illuminate\Database\Query\Builder $query The query | * @param \Illuminate\Database\Query\Builder $query The query | ||||
* @param callable $addQuery Additional tenant-scope query-modifier | * @param callable $addQuery Additional tenant-scope query-modifier | ||||
* | * | ||||
* @return \Illuminate\Database\Query\Builder | * @return \Illuminate\Database\Query\Builder | ||||
*/ | */ | ||||
protected function applyTenantScope($query, $addQuery = null) | protected function applyTenantScope($query, $addQuery = null) | ||||
Show All 24 Lines |