53 lines
1.5 KiB
PHP
53 lines
1.5 KiB
PHP
<?php
|
|
|
|
namespace App\Dashboard\Stats;
|
|
|
|
use App\Enums\PublishStatusEnum;
|
|
use App\Models\RouteArticle;
|
|
use App\Support\DateRange;
|
|
|
|
class PublishSuccessRate extends DailySeriesStat
|
|
{
|
|
public function key(): string
|
|
{
|
|
return 'publish-success-rate';
|
|
}
|
|
|
|
public function label(): string
|
|
{
|
|
return 'Publish Success Rate';
|
|
}
|
|
|
|
protected function series(DateRange $range, array $days): SeriesResult
|
|
{
|
|
// Buckets follow updated_at, so a retry re-dates its article to the retry day.
|
|
$attempts = RouteArticle::query()
|
|
->toBase()
|
|
->whereBetween('updated_at', [$range->from, $range->to])
|
|
->whereIn('publish_status', PublishStatusEnum::settledValues())
|
|
->selectRaw(
|
|
'DATE(updated_at) as bucket, COUNT(*) as total, SUM(CASE WHEN publish_status = ? THEN 1 ELSE 0 END) as published',
|
|
[PublishStatusEnum::PUBLISHED->value],
|
|
)
|
|
->groupBy('bucket')
|
|
->get()
|
|
->keyBy('bucket');
|
|
|
|
$values = array_map(
|
|
function (string $day) use ($attempts): ?float {
|
|
$attempt = $attempts->get($day);
|
|
|
|
if ($attempt === null || (int) $attempt->total === 0) {
|
|
return null;
|
|
}
|
|
|
|
return round(((int) $attempt->published / (int) $attempt->total) * 100, 1);
|
|
},
|
|
$days,
|
|
);
|
|
|
|
return new SeriesResult($days, [
|
|
new Series('Publish Success Rate', $values, zeroIsMeaningful: true),
|
|
]);
|
|
}
|
|
}
|