You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

InvoiceOverview.php 2.8KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. <?php
  2. namespace App\Filament\Company\Resources\Sales\InvoiceResource\Widgets;
  3. use App\Enums\Accounting\InvoiceStatus;
  4. use App\Filament\Company\Resources\Sales\InvoiceResource\Pages\ListInvoices;
  5. use App\Utilities\Currency\CurrencyConverter;
  6. use Filament\Widgets\Concerns\InteractsWithPageTable;
  7. use Filament\Widgets\StatsOverviewWidget as BaseWidget;
  8. use Filament\Widgets\StatsOverviewWidget\Stat;
  9. use Illuminate\Support\Number;
  10. class InvoiceOverview extends BaseWidget
  11. {
  12. use InteractsWithPageTable;
  13. protected static ?string $pollingInterval = null;
  14. protected function getTablePage(): string
  15. {
  16. return ListInvoices::class;
  17. }
  18. protected function getStats(): array
  19. {
  20. $outstandingInvoices = $this->getPageTableQuery()
  21. ->whereNotIn('status', [
  22. InvoiceStatus::Paid,
  23. InvoiceStatus::Void,
  24. InvoiceStatus::Draft,
  25. InvoiceStatus::Overpaid,
  26. ]);
  27. $amountOutstanding = $outstandingInvoices
  28. ->clone()
  29. ->sum('amount_due');
  30. $amountOverdue = $outstandingInvoices
  31. ->clone()
  32. ->where('status', InvoiceStatus::Overdue)
  33. ->sum('amount_due');
  34. $amountDueWithin30Days = $outstandingInvoices
  35. ->clone()
  36. ->where('due_date', '>=', today())
  37. ->where('due_date', '<=', today()->addDays(30))
  38. ->sum('amount_due');
  39. $validInvoices = $this->getPageTableQuery()
  40. ->whereNotIn('status', [
  41. InvoiceStatus::Void,
  42. InvoiceStatus::Draft,
  43. ]);
  44. $totalValidInvoiceAmount = $validInvoices->clone()->sum('amount_due');
  45. $totalValidInvoiceCount = $validInvoices->clone()->count();
  46. $averageInvoiceTotal = $totalValidInvoiceCount > 0 ? $totalValidInvoiceAmount / $totalValidInvoiceCount : 0;
  47. $averagePaymentTime = $this->getPageTableQuery()
  48. ->whereNotNull('paid_at')
  49. ->selectRaw('AVG(TIMESTAMPDIFF(DAY, date, paid_at)) as avg_days')
  50. ->value('avg_days');
  51. return [
  52. Stat::make('Total Outstanding', CurrencyConverter::formatCentsToMoney($amountOutstanding))
  53. ->description('Includes ' . CurrencyConverter::formatCentsToMoney($amountOverdue) . ' overdue'),
  54. Stat::make('Due Within 30 Days', CurrencyConverter::formatCentsToMoney($amountDueWithin30Days)),
  55. Stat::make('Average Payment Time', Number::format($averagePaymentTime ?? 0, maxPrecision: 1) . ' days')
  56. ->description('From invoice date to payment received'),
  57. Stat::make('Average Invoice Total', CurrencyConverter::formatCentsToMoney($averageInvoiceTotal))
  58. ->description('Excludes void and draft invoices'),
  59. ];
  60. }
  61. }