Implement a comprehensive financial management suite within the Filament admin panel, including new resources for payments and discount codes, along with a financial dashboard. - feat(ui): add Filament Dashboard with finance overview and transaction widgets - feat(ui): implement PaymentResource for monitoring gateway transactions - feat(ui): complete DiscountCodeResource with full CRUD and filtering - feat(wallet): add automatic wallet creation on balance retrieval - fix(wallet): resolve null handling in isFrozen() and balance viewing - fix(db): correct enum type from 'percent' to 'percentage' in discount_codes migration - fix(api): update pricing calculation endpoint to /api/v1/calculate - test: add 21 new feature and service tests covering wallet, payment, and discount logic - chore: remove obsolete PaymentGatewayService and update project status
88 lines
2.8 KiB
PHP
88 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Widgets;
|
|
|
|
use App\Models\WalletTransaction;
|
|
use Filament\Widgets\ChartWidget;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class TransactionChartWidget extends ChartWidget
|
|
{
|
|
protected static ?string $pollingInterval = '60s';
|
|
protected static ?string $heading = 'روند تراکنشهای ۳۰ روز اخیر';
|
|
protected static ?string $maxHeight = '300px';
|
|
|
|
protected function getData(): array
|
|
{
|
|
$data = WalletTransaction::select(
|
|
DB::raw('DATE(created_at) as date'),
|
|
DB::raw('SUM(CASE WHEN type = "deposit" AND status = "completed" THEN amount ELSE 0 END) as deposits'),
|
|
DB::raw('SUM(CASE WHEN type IN ("withdrawal", "order_payment") AND status = "completed" THEN amount ELSE 0 END) as withdrawals')
|
|
)
|
|
->where('created_at', '>=', now()->subDays(30))
|
|
->groupBy('date')
|
|
->orderBy('date')
|
|
->get();
|
|
|
|
$labels = $data->pluck('date')->map(fn ($date) => \Morilog\Jalali\Jalalian::fromCarbon(\Carbon\Carbon::parse($date))->format('Y/m/d'))->toArray();
|
|
$deposits = $data->pluck('deposits')->toArray();
|
|
$withdrawals = $data->pluck('withdrawals')->toArray();
|
|
|
|
return [
|
|
'datasets' => [
|
|
[
|
|
'label' => 'واریزیها',
|
|
'data' => $deposits,
|
|
'borderColor' => '#10b981',
|
|
'backgroundColor' => 'rgba(16, 185, 129, 0.1)',
|
|
'fill' => true,
|
|
'tension' => 0.4,
|
|
],
|
|
[
|
|
'label' => 'برداشتها',
|
|
'data' => $withdrawals,
|
|
'borderColor' => '#f59e0b',
|
|
'backgroundColor' => 'rgba(245, 158, 11, 0.1)',
|
|
'fill' => true,
|
|
'tension' => 0.4,
|
|
],
|
|
],
|
|
'labels' => $labels,
|
|
];
|
|
}
|
|
|
|
protected function getType(): string
|
|
{
|
|
return 'line';
|
|
}
|
|
|
|
protected function getOptions(): array
|
|
{
|
|
return [
|
|
'plugins' => [
|
|
'legend' => [
|
|
'position' => 'top',
|
|
'labels' => [
|
|
'font' => [
|
|
'family' => 'inherit',
|
|
],
|
|
],
|
|
],
|
|
],
|
|
'scales' => [
|
|
'y' => [
|
|
'beginAtZero' => true,
|
|
'ticks' => [
|
|
'callback' => 'function(value) { return value.toLocaleString("fa-IR"); }',
|
|
],
|
|
],
|
|
'x' => [
|
|
'ticks' => [
|
|
'maxRotation' => 0,
|
|
],
|
|
],
|
|
],
|
|
];
|
|
}
|
|
}
|