diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f84fc6808c7d..3eac98dc73c6 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -52,7 +52,7 @@ class Kernel extends ConsoleKernel $schedule->command('ninja:check-data --database=db-ninja-01')->daily()->withoutOverlapping(); - $schedule->job(new ReminderJob)->daily()->withoutOverlapping(); + $schedule->job(new ReminderJob)->hourly()->withoutOverlapping(); $schedule->job(new CompanySizeCheck)->daily()->withoutOverlapping(); diff --git a/app/Http/Controllers/RecurringInvoiceController.php b/app/Http/Controllers/RecurringInvoiceController.php index 2a1751813dbb..c50c239ed196 100644 --- a/app/Http/Controllers/RecurringInvoiceController.php +++ b/app/Http/Controllers/RecurringInvoiceController.php @@ -206,11 +206,9 @@ class RecurringInvoiceController extends BaseController event(new RecurringInvoiceWasCreated($recurring_invoice, $recurring_invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); - $offset = $recurring_invoice->client->timezone_offset(); - $recurring_invoice->next_send_date = Carbon::parse($recurring_invoice->next_send_date)->addSeconds($offset); + $recurring_invoice->next_send_date = Carbon::parse($recurring_invoice->next_send_date)->startOfDay()->addSeconds($offset); $recurring_invoice->save(); - return $this->itemResponse($recurring_invoice); } diff --git a/app/Jobs/Ninja/SendReminders.php b/app/Jobs/Ninja/SendReminders.php index 5b7f58da2dba..45d6db5c92c0 100644 --- a/app/Jobs/Ninja/SendReminders.php +++ b/app/Jobs/Ninja/SendReminders.php @@ -178,16 +178,17 @@ class SendReminders implements ShouldQueue */ private function calculateScheduledDate($invoice, $schedule_reminder, $num_days_reminder) :?Carbon { + $offset = $invoice->client->timezone_offset(); switch ($schedule_reminder) { case 'after_invoice_date': - return Carbon::parse($invoice->date)->addDays($num_days_reminder)->startOfDay(); + return Carbon::parse($invoice->date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset); break; case 'before_due_date': - return Carbon::parse($invoice->due_date)->subDays($num_days_reminder)->startOfDay(); + return Carbon::parse($invoice->due_date)->subDays($num_days_reminder)->startOfDay()->addSeconds($offset); break; case 'after_due_date': - return Carbon::parse($invoice->due_date)->addDays($num_days_reminder)->startOfDay(); + return Carbon::parse($invoice->due_date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset); break; default: return null; diff --git a/app/Jobs/RecurringInvoice/SendRecurring.php b/app/Jobs/RecurringInvoice/SendRecurring.php index ab8c65bc8652..0fc68bbea707 100644 --- a/app/Jobs/RecurringInvoice/SendRecurring.php +++ b/app/Jobs/RecurringInvoice/SendRecurring.php @@ -70,9 +70,9 @@ class SendRecurring implements ShouldQueue nlog("updating recurring invoice dates"); /* Set next date here to prevent a recurring loop forming */ - $this->recurring_invoice->next_send_date = $this->recurring_invoice->nextSendDate()->format('Y-m-d'); + $this->recurring_invoice->next_send_date = $this->recurring_invoice->nextSendDate(); $this->recurring_invoice->remaining_cycles = $this->recurring_invoice->remainingCycles(); - $this->recurring_invoice->last_sent_date = date('Y-m-d'); + $this->recurring_invoice->last_sent_date = now(); /* Set completed if we don't have any more cycles remaining*/ if ($this->recurring_invoice->remaining_cycles == 0) { diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index 7d8b427e5dcb..8a53bd0a50ae 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -53,7 +53,7 @@ class ReminderJob implements ShouldQueue private function processReminders() { - Invoice::where('next_send_date', Carbon::today()->format('Y-m-d'))->with('invitations')->cursor()->each(function ($invoice) { + Invoice::whereDate('next_send_date', '<=', now())->with('invitations')->cursor()->each(function ($invoice) { if ($invoice->isPayable()) { $reminder_template = $invoice->calculateTemplate('invoice'); diff --git a/app/Models/Account.php b/app/Models/Account.php index 268317681fa7..201add658429 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -105,9 +105,6 @@ class Account extends BaseModel return $this->hasOne(Company::class, 'id', 'default_company_id'); } - /** - * @return BelongsTo - */ public function payment() { return $this->belongsTo(Payment::class)->withTrashed(); @@ -323,4 +320,5 @@ class Account extends BaseModel ]; } } + } diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index c8db14421780..31ec610d3d09 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -256,31 +256,33 @@ class RecurringInvoice extends BaseModel public function nextDateByFrequency($date) { + $offset = $this->client->timezone_offset(); + switch ($this->frequency_id) { case self::FREQUENCY_DAILY: - return Carbon::parse($date)->addDay(); + return Carbon::parse($date)->startOfDay()->addDay()->addSeconds($offset); case self::FREQUENCY_WEEKLY: - return Carbon::parse($date)->addWeek(); + return Carbon::parse($date)->startOfDay()->addWeek()->addSeconds($offset); case self::FREQUENCY_TWO_WEEKS: - return Carbon::parse($date)->addWeeks(2); + return Carbon::parse($date)->startOfDay()->addWeeks(2)->addSeconds($offset); case self::FREQUENCY_FOUR_WEEKS: - return Carbon::parse($date)->addWeeks(4); + return Carbon::parse($date)->startOfDay()->addWeeks(4)->addSeconds($offset); case self::FREQUENCY_MONTHLY: - return Carbon::parse($date)->addMonthNoOverflow(); + return Carbon::parse($date)->startOfDay()->addMonthNoOverflow()->addSeconds($offset); case self::FREQUENCY_TWO_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(2); + return Carbon::parse($date)->startOfDay()->addMonthsNoOverflow(2)->addSeconds($offset); case self::FREQUENCY_THREE_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(3); + return Carbon::parse($date)->startOfDay()->addMonthsNoOverflow(3)->addSeconds($offset); case self::FREQUENCY_FOUR_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(4); + return Carbon::parse($date)->startOfDay()->addMonthsNoOverflow(4)->addSeconds($offset); case self::FREQUENCY_SIX_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(6); + return Carbon::parse($date)->addMonthsNoOverflow(6)->addSeconds($offset); case self::FREQUENCY_ANNUALLY: - return Carbon::parse($date)->addYear(); + return Carbon::parse($date)->startOfDay()->addYear()->addSeconds($offset); case self::FREQUENCY_TWO_YEARS: - return Carbon::parse($date)->addYears(2); + return Carbon::parse($date)->startOfDay()->addYears(2)->addSeconds($offset); case self::FREQUENCY_THREE_YEARS: - return Carbon::parse($date)->addYears(3); + return Carbon::parse($date)->startOfDay()->addYears(3)->addSeconds($offset); default: return null; } diff --git a/app/Services/Invoice/UpdateReminder.php b/app/Services/Invoice/UpdateReminder.php index 99a826ddfc22..5f2090a4cdc4 100644 --- a/app/Services/Invoice/UpdateReminder.php +++ b/app/Services/Invoice/UpdateReminder.php @@ -41,87 +41,89 @@ class UpdateReminder extends AbstractService return $this->invoice; //exit early } + $offset = $this->invoice->client->timezone_offset(); + $date_collection = collect(); if (is_null($this->invoice->reminder1_sent) && $this->settings->schedule_reminder1 == 'after_invoice_date' && $this->settings->num_days_reminder1 > 0) { - $reminder_date = Carbon::parse($this->invoice->date)->addDays($this->settings->num_days_reminder1); + $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder1_sent) && $this->settings->schedule_reminder1 == 'before_due_date' && $this->settings->num_days_reminder1 > 0) { - $reminder_date = Carbon::parse($this->invoice->due_date)->subDays($this->settings->num_days_reminder1); + $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder1)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder1_sent) && $this->settings->schedule_reminder1 == 'after_due_date' && $this->settings->num_days_reminder1 > 0) { - $reminder_date = Carbon::parse($this->invoice->due_date)->addDays($this->settings->num_days_reminder1); + $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder2_sent) && $this->settings->schedule_reminder2 == 'after_invoice_date' && $this->settings->num_days_reminder2 > 0) { - $reminder_date = Carbon::parse($this->invoice->date)->addDays($this->settings->num_days_reminder2); + $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder2_sent) && $this->settings->schedule_reminder2 == 'before_due_date' && $this->settings->num_days_reminder2 > 0) { - $reminder_date = Carbon::parse($this->invoice->due_date)->subDays($this->settings->num_days_reminder2); + $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder2)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder2_sent) && $this->settings->schedule_reminder2 == 'after_due_date' && $this->settings->num_days_reminder2 > 0) { - $reminder_date = Carbon::parse($this->invoice->due_date)->addDays($this->settings->num_days_reminder2); + $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder3_sent) && $this->settings->schedule_reminder3 == 'after_invoice_date' && $this->settings->num_days_reminder3 > 0) { - $reminder_date = Carbon::parse($this->invoice->date)->addDays($this->settings->num_days_reminder3); + $reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder3_sent) && $this->settings->schedule_reminder3 == 'before_due_date' && $this->settings->num_days_reminder3 > 0) { - $reminder_date = Carbon::parse($this->invoice->due_date)->subDays($this->settings->num_days_reminder3); + $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder3)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } if (is_null($this->invoice->reminder3_sent) && $this->settings->schedule_reminder3 == 'after_due_date' && $this->settings->num_days_reminder3 > 0) { - $reminder_date = Carbon::parse($this->invoice->due_date)->addDays($this->settings->num_days_reminder3); + $reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset); if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))); - $date_collection->push($reminder_date->format('Y-m-d')); + $date_collection->push($reminder_date); } $this->invoice->next_send_date = $date_collection->sort()->first(); diff --git a/database/migrations/2021_06_10_221012_add_ninja_portal_column_to_accounts_table.php b/database/migrations/2021_06_10_221012_add_ninja_portal_column_to_accounts_table.php new file mode 100644 index 000000000000..1439d794f6f0 --- /dev/null +++ b/database/migrations/2021_06_10_221012_add_ninja_portal_column_to_accounts_table.php @@ -0,0 +1,30 @@ +text('ninja_portal_url')->default(''); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + + } +} diff --git a/tests/Feature/ReminderTest.php b/tests/Feature/ReminderTest.php index 3651be8c7f5b..1dc98494c202 100644 --- a/tests/Feature/ReminderTest.php +++ b/tests/Feature/ReminderTest.php @@ -77,7 +77,7 @@ class ReminderTest extends TestCase $this->invoice->service()->markSent(); $this->invoice->service()->setReminder($settings)->save(); - $this->assertEquals($this->invoice->next_send_date, Carbon::now()->addDays(7)->format('Y-m-d')); + $this->assertEquals(Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'), Carbon::now()->addDays(7)->format('Y-m-d')); // ReminderJob::dispatchNow(); } @@ -106,7 +106,7 @@ class ReminderTest extends TestCase $this->invoice->fresh(); - $this->assertEquals($this->invoice->next_send_date, now()->format('Y-m-d')); + $this->assertEquals(Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'), now()->format('Y-m-d')); } @@ -136,7 +136,7 @@ class ReminderTest extends TestCase $this->invoice->fresh(); - $this->assertEquals($this->invoice->next_send_date, now()->format('Y-m-d')); + $this->assertEquals(Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'), now()->format('Y-m-d')); }