April 2026 waren Wirtschaft Feedback
This commit is contained in:
parent
02f2a4c23e
commit
9ce711d6b2
167 changed files with 25278 additions and 8518 deletions
|
|
@ -10,19 +10,19 @@ use Illuminate\Console\Command;
|
|||
|
||||
/**
|
||||
* Command für automatische Zahlungserinnerungen
|
||||
*
|
||||
*
|
||||
* Dieser Command wird als Cron-Job ausgeführt und sendet automatisch
|
||||
* Zahlungserinnerungen basierend auf den konfigurierten Intervallen.
|
||||
*
|
||||
*
|
||||
* Verwendung:
|
||||
* php artisan payments:reminders
|
||||
*
|
||||
*
|
||||
* Cron-Job Konfiguration (täglich um 9:00 Uhr):
|
||||
* 0 9 * * * cd /path/to/project && php artisan payments:reminders >> /dev/null 2>&1
|
||||
*
|
||||
*
|
||||
* Oder für stündliche Ausführung:
|
||||
* 0 * * * * cd /path/to/project && php artisan payments:reminders >> /dev/null 2>&1
|
||||
*
|
||||
*
|
||||
* Logs werden automatisch in storage/logs/laravel.log geschrieben
|
||||
*/
|
||||
class PaymentsReminders extends Command
|
||||
|
|
@ -33,16 +33,20 @@ class PaymentsReminders extends Command
|
|||
* @var string
|
||||
*/
|
||||
protected $signature = 'payments:reminders';
|
||||
|
||||
protected $description = 'Run Payments Reminders';
|
||||
|
||||
private $timeStart;
|
||||
|
||||
private $dev = false;
|
||||
|
||||
private $paymentReminderService;
|
||||
|
||||
private $stats = [
|
||||
'total_processed' => 0,
|
||||
'reminders_sent' => 0,
|
||||
'errors' => 0,
|
||||
'skipped' => 0
|
||||
'skipped' => 0,
|
||||
];
|
||||
|
||||
public function __construct(PaymentReminderService $paymentReminderService)
|
||||
|
|
@ -64,27 +68,29 @@ class PaymentsReminders extends Command
|
|||
|
||||
try {
|
||||
$this->functionReminder();
|
||||
|
||||
|
||||
$executionTime = round(microtime(true) - $this->timeStart, 2);
|
||||
$this->info("\n=== PAYMENT REMINDERS ABGESCHLOSSEN ===");
|
||||
$this->info("Ausführungszeit: {$executionTime} Sekunden");
|
||||
$this->info("Statistiken:");
|
||||
$this->info('Statistiken:');
|
||||
$this->info(" - Gesamt verarbeitet: {$this->stats['total_processed']}");
|
||||
$this->info(" - Erinnerungen gesendet: {$this->stats['reminders_sent']}");
|
||||
$this->info(" - Fehler: {$this->stats['errors']}");
|
||||
$this->info(" - Übersprungen: {$this->stats['skipped']}");
|
||||
|
||||
|
||||
\Log::info('PaymentsReminders Command completed successfully', [
|
||||
'execution_time' => $executionTime,
|
||||
'stats' => $this->stats
|
||||
'stats' => $this->stats,
|
||||
]);
|
||||
|
||||
return 0;
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('PaymentsReminders Command failed', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
$this->error('Command failed: ' . $e->getMessage());
|
||||
$this->error('Command failed: '.$e->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -95,43 +101,47 @@ class PaymentsReminders extends Command
|
|||
private function functionReminder()
|
||||
{
|
||||
$this->info('=== STARTE PAYMENT REMINDERS ===');
|
||||
|
||||
|
||||
// Hole alle aktiven PaymentReminder und gruppiere sie nach clearingtype
|
||||
$payment_reminders = PaymentReminder::where('active', true)->get();
|
||||
$this->info("Gefundene aktive PaymentReminder: " . $payment_reminders->count());
|
||||
|
||||
$this->info('Gefundene aktive PaymentReminder: '.$payment_reminders->count());
|
||||
|
||||
if ($payment_reminders->isEmpty()) {
|
||||
$this->warn("Keine aktiven PaymentReminder gefunden!");
|
||||
$this->warn('Keine aktiven PaymentReminder gefunden!');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Finde für jeden clearingtype das kleinste Intervall (in Tagen)
|
||||
$intervals = $this->paymentReminderService->getActiveIntervals();
|
||||
|
||||
$this->info("Gefundene clearingtypes mit kleinsten Intervallen:");
|
||||
foreach($intervals as $clearingtype => $interval){
|
||||
$this->info('Gefundene clearingtypes mit kleinsten Intervallen:');
|
||||
foreach ($intervals as $clearingtype => $interval) {
|
||||
$this->line(" - {$clearingtype}: {$interval} Tage");
|
||||
}
|
||||
|
||||
// Verarbeite jeden clearingtype mit seinem kleinsten Intervall
|
||||
foreach($intervals as $clearingtype => $interval){
|
||||
foreach ($intervals as $clearingtype => $interval) {
|
||||
$this->info("\n--- Verarbeite clearingtype: {$clearingtype} mit Intervall: {$interval} Tage ---");
|
||||
|
||||
|
||||
$date = Carbon::now()->subDays($interval);
|
||||
$this->line("Suche Zahlungen vor: " . $date->format('d.m.Y H:i:s'));
|
||||
$this->line('Suche Zahlungen vor: '.$date->format('d.m.Y H:i:s'));
|
||||
|
||||
// Hole nur die neueste ShoppingPayment pro shopping_order_id
|
||||
$shopping_payments = $this->paymentReminderService->getOpenPaymentsForClearingType($clearingtype, $interval);
|
||||
|
||||
$this->info("Gefundene offene Zahlungen für {$clearingtype}: " . $shopping_payments->count());
|
||||
|
||||
|
||||
$this->info("Gefundene offene Zahlungen für {$clearingtype}: ".$shopping_payments->count());
|
||||
|
||||
if ($shopping_payments->isEmpty()) {
|
||||
$this->line(" Keine Zahlungen für {$clearingtype} gefunden.");
|
||||
$this->line("Keine Zahlungen für {$clearingtype} gefunden.");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Verarbeite jede Zahlung
|
||||
foreach($shopping_payments as $shopping_payment){
|
||||
$this->line('--- START processPayment VERARBEITUNG');
|
||||
|
||||
foreach ($shopping_payments as $shopping_payment) {
|
||||
$this->processPayment($shopping_payment, $clearingtype);
|
||||
}
|
||||
}
|
||||
|
|
@ -143,33 +153,32 @@ class PaymentsReminders extends Command
|
|||
private function processPayment($shopping_payment, $clearingtype)
|
||||
{
|
||||
$this->stats['total_processed']++;
|
||||
|
||||
|
||||
try {
|
||||
$this->line(" Verarbeite Order ID: {$shopping_payment->shopping_order_id}, Created: {$shopping_payment->created_at->format('d.m.Y H:i:s')}, Amount: {$shopping_payment->amount}, Reminder: {$shopping_payment->reminder}");
|
||||
|
||||
$this->line("Verarbeite Order ID: {$shopping_payment->shopping_order_id}, Created: {$shopping_payment->created_at->format('d.m.Y H:i:s')}, Amount: {$shopping_payment->amount}, Reminder: {$shopping_payment->reminder}");
|
||||
|
||||
// Prüfe ob eine Erinnerung gesendet werden soll
|
||||
if ($this->shouldSendReminder($shopping_payment, $clearingtype)) {
|
||||
$this->sendReminderForPayment($shopping_payment);
|
||||
} else {
|
||||
$this->line(" ⏭️ Übersprungen - Keine Erinnerung fällig");
|
||||
$this->line('Übersprungen - Keine Erinnerung fällig');
|
||||
$this->stats['skipped']++;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->error(" ❌ Fehler bei Order ID {$shopping_payment->shopping_order_id}: " . $e->getMessage());
|
||||
$this->error("Fehler bei Order ID {$shopping_payment->shopping_order_id}: ".$e->getMessage());
|
||||
$this->stats['errors']++;
|
||||
|
||||
|
||||
\Log::error('Error processing payment reminder', [
|
||||
'order_id' => $shopping_payment->shopping_order_id,
|
||||
'payment_id' => $shopping_payment->id,
|
||||
'error' => $e->getMessage()
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft ob eine Erinnerung für diese Zahlung gesendet werden soll
|
||||
*
|
||||
*
|
||||
* Logik:
|
||||
* - Erste Erinnerung: Nach X Tagen ab Bestelldatum
|
||||
* - Weitere Erinnerungen: Nach Y Tagen ab letzter Erinnerung
|
||||
|
|
@ -179,36 +188,55 @@ class PaymentsReminders extends Command
|
|||
// Hole alle aktiven Erinnerungen für diesen Clearingtype
|
||||
$payment_reminders = PaymentReminder::where('active', true)
|
||||
->where('clearingtype', $clearingtype)
|
||||
->orderBy('interval', 'asc')
|
||||
->orderBy('interval', 'asc') // von kein nach gross
|
||||
->get();
|
||||
|
||||
if ($payment_reminders->isEmpty()) {
|
||||
$this->line('shouldSendReminder - keine PaymentReminders');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wenn alle Erinnerungen bereits gesendet wurden
|
||||
if ($shopping_payment->reminder >= $payment_reminders->count()) {
|
||||
$this->line('shouldSendReminder - alle Erinnerungen wurden bereits gesendet');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hole die nächste Erinnerung
|
||||
$next_reminder = $payment_reminders[$shopping_payment->reminder];
|
||||
|
||||
$next_reminder = isset($payment_reminders[$shopping_payment->reminder]) ? $payment_reminders[$shopping_payment->reminder] : null;
|
||||
if ($next_reminder == null) {
|
||||
$next_reminder = isset($payment_reminders[0]) ? $payment_reminders[0] : null;
|
||||
if ($next_reminder == null) {
|
||||
$this->line('shouldSendReminder - keine Erinnerung gefunden');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->line("shouldSendReminder - nächste Erinnerung: {$next_reminder->interval} Tage");
|
||||
|
||||
// Wenn noch keine Erinnerung gesendet wurde, prüfe das erste Intervall
|
||||
if ($shopping_payment->reminder == 0) {
|
||||
if ($shopping_payment->reminder == null || $shopping_payment->reminder == 0) {
|
||||
$daysSinceOrder = $shopping_payment->created_at->diffInDays(now());
|
||||
$this->line("shouldSendReminder - no reminder send first intervall - Tage seit Bestellung: {$daysSinceOrder} : Next intervall: {$next_reminder->interval}");
|
||||
|
||||
return $daysSinceOrder >= $next_reminder->interval;
|
||||
}
|
||||
|
||||
|
||||
// Hole die nächste Erinnerung
|
||||
|
||||
// Wenn bereits Erinnerungen gesendet wurden, prüfe das nächste Intervall
|
||||
if ($shopping_payment->reminder_date) {
|
||||
$current_reminder = $payment_reminders[$shopping_payment->reminder - 1];
|
||||
$this->line("shouldSendReminder - letzte Erinnerung: {$current_reminder->interval} Tage");
|
||||
$interval_difference = $next_reminder->interval - $current_reminder->interval;
|
||||
|
||||
|
||||
$next_reminder_date = Carbon::parse($shopping_payment->reminder_date)->addDays($interval_difference);
|
||||
$this->line("shouldSendReminder - next reminder date: {$next_reminder_date->format('d.m.Y H:i:s')}");
|
||||
|
||||
return now()->gte($next_reminder_date);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -218,35 +246,34 @@ class PaymentsReminders extends Command
|
|||
private function sendReminderForPayment($shopping_payment)
|
||||
{
|
||||
try {
|
||||
$this->line(" 📧 Sende Erinnerung...");
|
||||
|
||||
$this->line('Sende Erinnerung...');
|
||||
|
||||
$result = $this->paymentReminderService->sendReminder($shopping_payment);
|
||||
|
||||
|
||||
if ($result) {
|
||||
$this->line(" ✅ Erinnerung erfolgreich gesendet");
|
||||
$this->line('Erinnerung erfolgreich gesendet');
|
||||
$this->stats['reminders_sent']++;
|
||||
|
||||
|
||||
// Log für Cron-Job
|
||||
\Log::info('Payment reminder sent via cron', [
|
||||
'order_id' => $shopping_payment->shopping_order_id,
|
||||
'payment_id' => $shopping_payment->id,
|
||||
'reminder_count' => $shopping_payment->reminder + 1,
|
||||
'email' => $shopping_payment->shopping_order->shopping_user->billing_email ?? 'N/A'
|
||||
'email' => $shopping_payment->shopping_order->shopping_user->billing_email ?? 'N/A',
|
||||
]);
|
||||
} else {
|
||||
$this->line(" ⚠️ Keine Erinnerung gesendet (keine weitere Erinnerung verfügbar)");
|
||||
$this->line('Keine Erinnerung gesendet (keine weitere Erinnerung verfügbar)');
|
||||
$this->stats['skipped']++;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->error(" ❌ Fehler beim Senden der Erinnerung: " . $e->getMessage());
|
||||
$this->error('Fehler beim Senden der Erinnerung: '.$e->getMessage());
|
||||
$this->stats['errors']++;
|
||||
|
||||
|
||||
\Log::error('Error sending payment reminder', [
|
||||
'order_id' => $shopping_payment->shopping_order_id,
|
||||
'payment_id' => $shopping_payment->id,
|
||||
'error' => $e->getMessage()
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,27 +19,27 @@ class Kernel extends ConsoleKernel
|
|||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
/*$schedule->command('payments:accounts')
|
||||
if (config('app.debug') == false) {
|
||||
$schedule->command('payments:accounts')
|
||||
->sendOutputTo(storage_path('logs/cron.log'))
|
||||
->appendOutputTo(storage_path('logs/cron-history.log'))
|
||||
->emailOutputOnFailure(config('app.exception_mail'))
|
||||
->onFailure(function () {
|
||||
\Log::error('Payments:accounts command failed');
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
$schedule->command('payments:reminders')
|
||||
->sendOutputTo(storage_path('logs/cron.log'))
|
||||
->appendOutputTo(storage_path('logs/cron-reminders.log'))
|
||||
->emailOutputOnFailure(config('app.exception_mail'))
|
||||
->onFailure(function () {
|
||||
\Log::error('Payments:reminders command failed');
|
||||
});
|
||||
->sendOutputTo(storage_path('logs/cron.log'))
|
||||
->appendOutputTo(storage_path('logs/cron-reminders.log'))
|
||||
->emailOutputOnFailure(config('app.exception_mail'))
|
||||
->onFailure(function () {
|
||||
\Log::error('Payments:reminders command failed');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue