60413bdebf
- BookingsTodayWidget, RecentBookingsTableWidget (Booking module) and RevenueChartWidget, PaymentFailureRateWidget (Payment module) dashboard widgets, auto-registered via each plugin's existing discoverWidgets(). - .gitea/workflows/tests.yml: Postgres-backed Pest run on push/PR. - Landing page (resources/views/welcome.blade.php) now shows the Famous Linnyone4 EV logo with a single admin login link, and the Filament admin panel uses the same logo as its brand logo.
43 lines
1.3 KiB
PHP
43 lines
1.3 KiB
PHP
<?php
|
|
|
|
namespace Modules\Payment\Filament\Widgets;
|
|
|
|
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
|
|
use Filament\Widgets\StatsOverviewWidget\Stat;
|
|
use Modules\Payment\Enums\PaymentStatus;
|
|
use Modules\Payment\Models\Payment;
|
|
|
|
/**
|
|
* Failure rate over the trailing 30 days, among payments that reached a
|
|
* terminal state (completed or failed) — pending attempts are excluded
|
|
* since they haven't resolved either way yet.
|
|
*/
|
|
class PaymentFailureRateWidget extends BaseWidget
|
|
{
|
|
protected static ?int $sort = 3;
|
|
|
|
protected function getStats(): array
|
|
{
|
|
$since = today()->subDays(30);
|
|
|
|
$completed = Payment::query()
|
|
->where('status', PaymentStatus::Completed)
|
|
->where('initiated_at', '>=', $since)
|
|
->count();
|
|
|
|
$failed = Payment::query()
|
|
->where('status', PaymentStatus::Failed)
|
|
->where('initiated_at', '>=', $since)
|
|
->count();
|
|
|
|
$resolved = $completed + $failed;
|
|
$rate = $resolved > 0 ? round(($failed / $resolved) * 100, 1) : 0.0;
|
|
|
|
return [
|
|
Stat::make('Payment Failure Rate', $rate.'%')
|
|
->description("{$failed} failed of {$resolved} resolved (last 30 days)")
|
|
->color($rate >= 20 ? 'danger' : ($rate > 0 ? 'warning' : 'success')),
|
|
];
|
|
}
|
|
}
|