Last active
April 19, 2020 03:48
-
-
Save cwilby/6a63eb44bf2e89759410b640c757035f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Laravel\Nova\Metrics; | |
use Illuminate\Database\Eloquent\Builder; | |
use Illuminate\Support\Carbon; | |
use Laravel\Nova\Nova; | |
abstract class Value extends RangedMetric | |
{ | |
/** | |
* The element's component. | |
* | |
* @var string | |
*/ | |
public $component = 'value-metric'; | |
/** | |
* The value's precision when rounding. | |
* | |
* @var int | |
*/ | |
public $precision = 0; | |
/** | |
* Return a value result showing the growth of an count aggregate over time. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Illuminate\Database\Eloquent\Builder|string $model | |
* @param string|null $column | |
* @param string|null $dateColumn | |
* @return \Laravel\Nova\Metrics\ValueResult | |
*/ | |
public function count($request, $model, $column = null, $dateColumn = null) | |
{ | |
return $this->aggregate($request, $model, 'count', $column, $dateColumn); | |
} | |
/** | |
* Return a value result showing the growth of an average aggregate over time. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Illuminate\Database\Eloquent\Builder|string $model | |
* @param string $column | |
* @param string|null $dateColumn | |
* @return \Laravel\Nova\Metrics\ValueResult | |
*/ | |
public function average($request, $model, $column, $dateColumn = null) | |
{ | |
return $this->aggregate($request, $model, 'avg', $column, $dateColumn); | |
} | |
/** | |
* Return a value result showing the growth of a sum aggregate over time. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Illuminate\Database\Eloquent\Builder|string $model | |
* @param string $column | |
* @param string|null $dateColumn | |
* @return \Laravel\Nova\Metrics\ValueResult | |
*/ | |
public function sum($request, $model, $column, $dateColumn = null) | |
{ | |
return $this->aggregate($request, $model, 'sum', $column, $dateColumn); | |
} | |
/** | |
* Return a value result showing the growth of a maximum aggregate over time. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Illuminate\Database\Eloquent\Builder|string $model | |
* @param string $column | |
* @param string|null $dateColumn | |
* @return \Laravel\Nova\Metrics\ValueResult | |
*/ | |
public function max($request, $model, $column, $dateColumn = null) | |
{ | |
return $this->aggregate($request, $model, 'max', $column, $dateColumn); | |
} | |
/** | |
* Return a value result showing the growth of a minimum aggregate over time. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Illuminate\Database\Eloquent\Builder|string $model | |
* @param string $column | |
* @param string|null $dateColumn | |
* @return \Laravel\Nova\Metrics\ValueResult | |
*/ | |
public function min($request, $model, $column, $dateColumn = null) | |
{ | |
return $this->aggregate($request, $model, 'min', $column, $dateColumn); | |
} | |
/** | |
* Return a value result showing the growth of a model over a given time frame. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Illuminate\Database\Eloquent\Builder|string $model | |
* @param string $function | |
* @param string|null $column | |
* @param string|null $dateColumn | |
* @return \Laravel\Nova\Metrics\ValueResult | |
*/ | |
protected function aggregate($request, $model, $function, $column = null, $dateColumn = null) | |
{ | |
$query = $model instanceof Builder ? $model : (new $model)->newQuery(); | |
$column = $column ?? $query->getModel()->getQualifiedKeyName(); | |
$previousValue = round(with(clone $query)->whereBetween( | |
$dateColumn ?? $query->getModel()->getCreatedAtColumn(), | |
$this->previousRange($request->range) | |
)->{$function}($column), $this->precision); | |
return $this->result( | |
round(with(clone $query)->whereBetween( | |
$dateColumn ?? $query->getModel()->getCreatedAtColumn(), | |
$this->currentRange($request->range) | |
)->{$function}($column), $this->precision) | |
)->previous($previousValue); | |
} | |
/** | |
* Calculate the previous range and calculate any short-cuts. | |
* | |
* @param string|int $range | |
* @return array | |
*/ | |
protected function previousRange($range) | |
{ | |
if ($range == 'TODAY') { | |
return [ | |
now()->modify('yesterday')->setTime(0, 0), | |
now()->subDays(1), | |
]; | |
} | |
if ($range == 'MTD') { | |
return [ | |
now()->modify('first day of previous month')->setTime(0, 0), | |
now()->subMonthsNoOverflow(1), | |
]; | |
} | |
if ($range == 'QTD') { | |
return $this->previousQuarterRange(); | |
} | |
if ($range == 'YTD') { | |
return [ | |
now()->subYears(1)->firstOfYear()->setTime(0, 0), | |
now()->subYearsNoOverflow(1), | |
]; | |
} | |
return [ | |
now()->subDays($range * 2), | |
now()->subDays($range), | |
]; | |
} | |
/** | |
* Calculate the previous quarter range. | |
* | |
* @param string | |
* | |
* @return array | |
*/ | |
protected function previousQuarterRange() | |
{ | |
return [ | |
Carbon::firstDayOfPreviousQuarter()->setTimezone()->setTime(0, 0), | |
now()->subMonthsNoOverflow(3), | |
]; | |
} | |
/** | |
* Calculate the current range and calculate any short-cuts. | |
* | |
* @param string|int $range | |
* @param string | |
* @return array | |
*/ | |
protected function currentRange($range) | |
{ | |
if ($range == 'TODAY') { | |
return [ | |
now()->today(), | |
now(), | |
]; | |
} | |
if ($range == 'MTD') { | |
return [ | |
now()->firstOfMonth(), | |
now(), | |
]; | |
} | |
if ($range == 'QTD') { | |
return $this->currentQuarterRange(); | |
} | |
if ($range == 'YTD') { | |
return [ | |
now()->firstOfYear(), | |
now(), | |
]; | |
} | |
return [ | |
now()->subDays($range), | |
now(), | |
]; | |
} | |
/** | |
* Calculate the previous quarter range. | |
* | |
* @param string | |
* | |
* @return array | |
*/ | |
protected function currentQuarterRange() | |
{ | |
return [ | |
Carbon::firstDayOfQuarter(), | |
now(), | |
]; | |
} | |
/** | |
* Set the precision level used when rounding the value. | |
* | |
* @param int $precision | |
* @return $this | |
*/ | |
public function precision($precision = 0) | |
{ | |
$this->precision = $precision; | |
return $this; | |
} | |
/** | |
* Create a new value metric result. | |
* | |
* @param mixed $value | |
* @return \Laravel\Nova\Metrics\ValueResult | |
*/ | |
public function result($value) | |
{ | |
return new ValueResult($value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment