runCronJob('invoices_created', function ($number = 0) { Service::where('status', 'active')->where('expires_at', '<', now()->addDays((int) config('settings.cronjob_invoice', 7)))->get()->each(function ($service) use (&$number) { // Does the service have already a pending invoice? if ($service->invoices()->where('status', 'pending')->exists() || $service->cancellation()->exists()) { return; } // Calculate if we should edit the price because of the coupon if ($service->coupon) { // Calculate what iteration of the coupon we are in $iteration = $service->invoices()->count() + 1; if ($iteration == $service->coupon->recurring) { // Calculate the price $service->price = $service->calculatePrice(); $service->save(); } } // If service price is 0, immediately activate next period if ($service->price <= 0) { (new \App\Services\Service\RenewServiceService)->handle($service); $number++; return; } // Create invoice $invoice = $service->invoices()->make([ 'user_id' => $service->user_id, 'status' => 'pending', 'due_at' => $service->expires_at, 'currency_code' => $service->currency_code, ]); $invoice->save(); // Create invoice items $invoice->items()->create([ 'reference_id' => $service->id, 'reference_type' => Service::class, 'price' => $service->price, 'quantity' => $service->quantity, 'description' => $service->description, ]); $invoice = $invoice->refresh(); $this->payInvoiceWithCredits($invoice); // Charge billing agreements if ($service->billing_agreement_id && $invoice->fresh()->status === 'pending') { DB::afterCommit(function () use ($invoice, $service) { try { ExtensionHelper::charge( $service->billingAgreement->gateway, $invoice, $service->billingAgreement ); $this->successFullCharges++; } catch (Exception $e) { // Ignore errors here NotificationHelper::invoicePaymentFailedNotification($invoice->user, $invoice); } }); } $number++; }); return $number; }); $this->runCronJob('orders_cancelled', function ($number = 0) { // Cancel services if first invoice is not paid after x days Service::where('status', 'pending')->whereDoesntHave('invoices', function ($query) { $query->where('status', 'paid'); })->where('created_at', '<', now()->subDays((int) config('settings.cronjob_order_cancel', 7)))->get()->each(function ($service) use (&$number) { $service->invoices()->where('status', 'pending')->update(['status' => 'cancelled']); $service->update(['status' => 'cancelled']); if ($service->product->stock !== null) { $service->product->increment('stock', $service->quantity); } $number++; }); return $number; }); $this->runCronJob('upgrade_invoices_updated', function ($number = 0) { // Update pending upgrade invoices ServiceUpgrade::where('status', 'pending')->get()->each(function ($upgrade) use (&$number) { if ($upgrade->service->expires_at < now()) { $upgrade->update(['status' => 'cancelled']); $upgrade->invoice->update(['status' => 'cancelled']); $number++; return; } $upgrade->invoice->items()->update([ 'price' => $upgrade->calculatePrice()->price, ]); $number++; }); return $number; }); $this->runCronJob('services_suspended', function ($number = 0) { // Suspend orders if due date is overdue for x days Service::where('status', 'active')->where('expires_at', '<', now()->subDays((int) config('settings.cronjob_order_suspend', 2)))->get()->each(function ($service) use (&$number) { SuspendJob::dispatch($service); $service->update(['status' => 'suspended']); $number++; }); return $number; }); $this->runCronJob('services_terminated', function ($number = 0) { // Terminate orders if due date is overdue for x days Service::where('status', 'suspended')->where('expires_at', '<', now()->subDays((int) config('settings.cronjob_order_terminate', 14)))->each(function ($service) use (&$number) { TerminateJob::dispatch($service); $service->update(['status' => 'cancelled']); // Cancel outstanding invoices $service->invoices()->where('status', 'pending')->update(['status' => 'cancelled']); if ($service->product->stock !== null) { $service->product->increment('stock', $service->quantity); } $number++; }); return $number; }); $this->runCronJob('tickets_closed', function ($number = 0) { // Close tickets if no response for x days Ticket::where('status', 'replied')->each(function ($ticket) use (&$number) { $lastMessage = $ticket->messages()->latest('created_at')->first(); if ($lastMessage && $lastMessage->created_at < now()->subDays((int) config('settings.cronjob_close_ticket', 7))) { $ticket->update(['status' => 'closed']); $number++; } }); return $number; }); $this->runCronJob('email_logs_deleted', function ($number = 0) { $number = Notification::where('created_at', '<', now()->subDays((int) config('settings.cronjob_delete_email_logs', 90)))->count(); // Delete email logs older then x Notification::where('created_at', '<', now()->subDays((int) config('settings.cronjob_delete_email_logs', 90)))->delete(); return $number; }); } catch (Exception $e) { DB::rollBack(); NotificationHelper::sendSystemEmailNotification('Cron Job Error', <<
{$e->getMessage()}.