diff --git a/app/Console/Commands/RecurringCheck.php b/app/Console/Commands/RecurringCheck.php new file mode 100644 index 000000000..bc10544f0 --- /dev/null +++ b/app/Console/Commands/RecurringCheck.php @@ -0,0 +1,186 @@ + $company->id]); + + // Override settings and currencies + Overrider::load('settings'); + Overrider::load('currencies'); + + $company->setSettings(); + + $recurring = $company->recurring(); + + foreach ($recurring as $recur) { + $schedule = $this->schedule($recur); + + $current = Date::parse($schedule->current()->getStart()); + + // Check if should recur today + if ($today->ne($current)) { + continue; + } + + $type = end(explode('\\', $recur->recurable_type)); + + $model = $type::find($recur->recurable_id); + + if (!$model) { + continue; + } + + switch ($type) { + case 'Bill': + $this->recurBill($company, $model); + break; + case 'Invoice': + $this->recurInvoice($company, $model); + break; + case 'Payment': + case 'Revenue': + $model->duplicate(); + break; + } + } + } + + // Unset company_id + session()->forget('company_id'); + } + + protected function recurInvoice($company, $model) + { + $clone = $model->duplicate(); + + // Add invoice history + InvoiceHistory::create([ + 'company_id' => session('company_id'), + 'invoice_id' => $clone->id, + 'status_code' => 'draft', + 'notify' => 0, + 'description' => trans('messages.success.added', ['type' => $clone->invoice_number]), + ]); + + // Notify the customer + if ($clone->customer && !empty($clone->customer_email)) { + $clone->customer->notify(new InvoiceNotification($clone)); + } + + // Notify all users assigned to this company + foreach ($company->users as $user) { + if (!$user->can('read-notifications')) { + continue; + } + + $user->notify(new InvoiceNotification($clone)); + } + + // Update next invoice number + $this->increaseNextInvoiceNumber(); + } + + protected function recurBill($company, $model) + { + $clone = $model->duplicate(); + + // Add bill history + BillHistory::create([ + 'company_id' => session('company_id'), + 'bill_id' => $clone->id, + 'status_code' => 'draft', + 'notify' => 0, + 'description' => trans('messages.success.added', ['type' => $clone->bill_number]), + ]); + + // Notify all users assigned to this company + foreach ($company->users as $user) { + if (!$user->can('read-notifications')) { + continue; + } + + $user->notify(new BillNotification($clone)); + } + } + + protected function schedule($recur) + { + $config = new ArrayTransformerConfig(); + $config->enableLastDayOfMonthFix(); + + $transformer = new ArrayTransformer(); + $transformer->setConfig($config); + + return $transformer->transform($this->rule($recur)); + } + + protected function rule($recur) + { + $rule = (new Rule()) + ->setStartDate($recur->started_at) + ->setTimezone(setting('general.timezone')) + ->setFreq(strtoupper($recur->frequency)) + ->setInterval($recur->interval) + ->setCount($recur->count); + + return $rule; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 2698c72d2..8aa2e40da 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -18,6 +18,7 @@ class Kernel extends ConsoleKernel Commands\Install::class, Commands\InvoiceReminder::class, Commands\ModuleInstall::class, + Commands\RecurringCheck::class, ]; /** diff --git a/app/Models/Company/Company.php b/app/Models/Company/Company.php index eb9f2190f..a9ecf4ff2 100644 --- a/app/Models/Company/Company.php +++ b/app/Models/Company/Company.php @@ -106,6 +106,11 @@ class Company extends Eloquent return $this->hasMany('App\Models\Expense\Payment'); } + public function recurring() + { + return $this->hasMany('App\Models\Common\Recurring'); + } + public function revenues() { return $this->hasMany('App\Models\Income\Revenue'); diff --git a/composer.json b/composer.json index 3aaab5d36..5c2b55bf0 100644 --- a/composer.json +++ b/composer.json @@ -32,6 +32,7 @@ "nwidart/laravel-modules": "1.*", "plank/laravel-mediable": "2.5.*", "santigarcor/laratrust": "4.0.*", + "simshaun/recurr": "3.0.*", "sofa/eloquence": "5.4.*", "tucker-eric/eloquentfilter": "1.1.*" },