diff --git a/app/Console/Commands/ProcessInvoiceReminders.php b/app/Console/Commands/ProcessInvoiceReminders.php index 4f59d641..6fdc7a4d 100644 --- a/app/Console/Commands/ProcessInvoiceReminders.php +++ b/app/Console/Commands/ProcessInvoiceReminders.php @@ -19,17 +19,28 @@ public function __construct(BillingService $billingService) } public function handle() - { +{ + if (cache()->get('processing_invoice_reminders')) { + $this->warn('Invoice reminder processing is already running'); + return Command::FAILURE; + } + + cache()->put('processing_invoice_reminders', true, 60); // Lock for 60 minutes + + try { $this->info('Processing invoice reminders...'); - // Process upcoming invoice reminders $upcomingCount = $this->billingService->sendUpcomingInvoiceReminders(); $this->info("Sent {$upcomingCount} upcoming invoice reminders"); - // Process overdue invoice reminders $overdueCount = $this->billingService->sendOverdueReminders(); $this->info("Sent {$overdueCount} overdue invoice reminders"); + cache()->forget('processing_invoice_reminders'); return Command::SUCCESS; + } catch (\Exception $e) { + cache()->forget('processing_invoice_reminders'); + $this->error("Error processing reminders: " . $e->getMessage()); + return Command::FAILURE; } } \ No newline at end of file diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 4fb3b370..cfb0e115 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -24,12 +24,37 @@ protected function schedule(Schedule $schedule): void $schedule->command('audit:prune')->daily(); $schedule->call(function () { - $reports = Report::whereNotNull('schedule')->get(); - foreach ($reports as $report) { - if ($this->shouldGenerateReport($report)) { - app(ReportGenerationService::class)->generateReport($report); - $report->update(['last_generated_at' => now()]); + try { + $reports = Report::query() + ->whereNotNull('schedule') + ->where(function ($query) { + $query->whereNull('last_generated_at') + ->orWhere('last_generated_at', '<=', now()->subHour()); + }) + ->get(); + + foreach ($reports as $report) { + try { + if ($this->shouldGenerateReport($report)) { + app(ReportGenerationService::class)->generateReport($report); + $report->update([ + 'last_generated_at' => now(), + 'last_generation_status' => 'success' + ]); + } + } catch (\Exception $e) { + \Log::error('Failed to generate report: ' . $e->getMessage(), [ + 'report_id' => $report->id, + 'error' => $e->getMessage() + ]); + $report->update([ + 'last_generation_status' => 'failed', + 'last_error' => $e->getMessage() + ]); + } } + } catch (\Exception $e) { + \Log::error('Failed to process report generation schedule: ' . $e->getMessage()); } })->hourly(); } @@ -40,11 +65,18 @@ protected function shouldGenerateReport(Report $report): bool return true; } + if (!isset($report->schedule['frequency'])) { + return false; + } + $schedule = $report->schedule; + $lastGenerated = $report->last_generated_at; + return match($schedule['frequency']) { - 'daily' => $report->last_generated_at->diffInDays(now()) >= 1, - 'weekly' => $report->last_generated_at->diffInWeeks(now()) >= 1, - 'monthly' => $report->last_generated_at->diffInMonths(now()) >= 1, + 'daily' => $lastGenerated->diffInDays(now()) >= 1, + 'weekly' => $lastGenerated->diffInWeeks(now()) >= 1, + 'monthly' => $lastGenerated->diffInMonths(now()) >= 1, + 'hourly' => $lastGenerated->diffInHours(now()) >= 1, default => false }; }