From 96785e27bf881e80a16440e9de910dec2037e54c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 24 Sep 2023 16:51:35 +1000 Subject: [PATCH] Tests for reminders with partial due dates --- app/Services/Invoice/ApplyPaymentAmount.php | 5 +- app/Services/Invoice/InvoiceService.php | 3 + app/Utils/Traits/MakesReminders.php | 6 +- tests/Feature/ReminderTest.php | 183 ++++++++++++++++++++ 4 files changed, 192 insertions(+), 5 deletions(-) diff --git a/app/Services/Invoice/ApplyPaymentAmount.php b/app/Services/Invoice/ApplyPaymentAmount.php index b200148538ab..468e4524c216 100644 --- a/app/Services/Invoice/ApplyPaymentAmount.php +++ b/app/Services/Invoice/ApplyPaymentAmount.php @@ -31,7 +31,7 @@ class ApplyPaymentAmount extends AbstractService } public function run() - {nlog("apply payment amount"); + { if ($this->invoice->status_id == Invoice::STATUS_DRAFT) { $this->invoice = $this->invoice->service()->markSent()->save(); } @@ -75,10 +75,9 @@ class ApplyPaymentAmount extends AbstractService ->setCalculatedStatus() ->applyNumber(); - nlog("check for partials"); if ($has_partial) { - nlog("has partial"); + $this->invoice->partial = max(0, $this->invoice->partial - $payment->amount); $invoice_service->checkReminderStatus(); } diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index a42009c1246e..7e82106ec82a 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -304,6 +304,9 @@ class InvoiceService public function checkReminderStatus(): self { + if($this->invoice->partial == 0) + $this->invoice->partial_due_date = null; + if($this->invoice->partial == 0 && $this->invoice->balance > 0) { $this->invoice->reminder1_sent = null; diff --git a/app/Utils/Traits/MakesReminders.php b/app/Utils/Traits/MakesReminders.php index 753fb1d98608..2f3de1aebb2d 100644 --- a/app/Utils/Traits/MakesReminders.php +++ b/app/Utils/Traits/MakesReminders.php @@ -34,9 +34,11 @@ trait MakesReminders case 'after_invoice_date': return Carbon::parse($this->date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset)->isSameDay(Carbon::now()); case 'before_due_date': - return Carbon::parse($this->due_date)->subDays($num_days_reminder)->startOfDay()->addSeconds($offset)->isSameDay(Carbon::now()); + $partial_or_due_date = ($this->partial > 0 && isset($this->partial_due_date)) ? $this->partial_due_date : $this->due_date; + return Carbon::parse($partial_or_due_date)->subDays($num_days_reminder)->startOfDay()->addSeconds($offset)->isSameDay(Carbon::now()); case 'after_due_date': - return Carbon::parse($this->due_date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset)->isSameDay(Carbon::now()); + $partial_or_due_date = ($this->partial > 0 && isset($this->partial_due_date)) ? $this->partial_due_date : $this->due_date; + return Carbon::parse($partial_or_due_date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset)->isSameDay(Carbon::now()); default: return null; } diff --git a/tests/Feature/ReminderTest.php b/tests/Feature/ReminderTest.php index f963a048628e..ba2c5a110258 100644 --- a/tests/Feature/ReminderTest.php +++ b/tests/Feature/ReminderTest.php @@ -158,6 +158,189 @@ class ReminderTest extends TestCase } + + public function testMultiplePartialDueDateReminderWithEndlessReminder() + { + + $settings = $this->company->settings; + $settings->enable_reminder1 = true; + $settings->schedule_reminder1 = 'before_due_date'; + $settings->num_days_reminder1 = 1; + $settings->enable_reminder2 = true; + $settings->schedule_reminder2 = 'after_due_date'; + $settings->num_days_reminder2 = 0; + $settings->enable_reminder3 = true; + $settings->schedule_reminder3 = 'after_due_date'; + $settings->num_days_reminder3 = 7; + $settings->timezone_id = '29'; + $settings->entity_send_time = 0; + $settings->endless_reminder_frequency_id = '1'; + $settings->enable_reminder_endless = true; + + $this->buildData(($settings)); + + $this->invoice->reminder1_sent = null; + $this->invoice->reminder2_sent = null; + $this->invoice->reminder3_sent = null; + $this->invoice->date = now()->startOfDay(); + $this->invoice->partial = 10; + $this->invoice->amount = 100; + $this->invoice->balance = 100; + $this->invoice->partial_due_date = now()->startOfDay()->addDays(7); + $this->invoice->due_date = now()->startOfDay()->addMonth(); + $this->invoice->service()->setReminder($settings)->save(); + + $this->invoice = $this->invoice->fresh(); + + $this->assertEquals(now()->startOfDay()->addDays(6)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d')); + $this->assertTrue($this->invoice->hasPartial()); + + // nlog("partial due date = {$this->invoice->partial_due_date}"); + // nlog("due date = {$this->invoice->due_date}"); + // nlog("travelling to: ". Carbon::parse($this->invoice->partial_due_date)->subDay()->addHour()->startOfDay()->format("Y-m-d")); + // nlog("Reminder 1 test"); + + $this->travelTo(Carbon::parse($this->invoice->partial_due_date)->subDay()->addHours(2)->startOfDay()); + (new ReminderJob())->handle(); + + $this->invoice = $this->invoice->fresh(); + $this->assertEquals(now()->format('Y-m-d'), Carbon::parse($this->invoice->reminder_last_sent)->format('Y-m-d')); + $this->assertNotNull($this->invoice->reminder1_sent); + $this->assertEquals(Carbon::parse($this->invoice->partial_due_date)->startOfDay()->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d')); + + $this->travelTo(Carbon::parse($this->invoice->partial_due_date)->startOfDay()); + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertEquals(now()->format('Y-m-d'), Carbon::parse($this->invoice->reminder_last_sent)->format('Y-m-d')); + $this->assertNotNull($this->invoice->reminder2_sent); + $this->assertEquals(Carbon::parse($this->invoice->partial_due_date)->startOfDay()->addDays(7)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d')); + + $this->travelTo(Carbon::parse($this->invoice->partial_due_date)->addDays(7)->startOfDay()); + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertEquals(now()->format('Y-m-d'), Carbon::parse($this->invoice->reminder_last_sent)->format('Y-m-d')); + $this->assertNotNull($this->invoice->reminder3_sent); + $this->assertEquals(Carbon::parse($this->invoice->partial_due_date)->startOfDay()->addDays(8)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d')); + + $this->invoice->service()->applyPaymentAmount(100)->save(); + $this->invoice = $this->invoice->fresh(); + $this->assertNull($this->invoice->next_send_date); + $this->assertEquals(0, $this->invoice->partial); + $this->assertNull($this->invoice->partial_due_date); + + $this->invoice->payments()->each(function ($payment) { + $payment->service()->deletePayment(); + }); + + $this->invoice = $this->invoice->fresh(); + + $this->assertEquals(0, $this->invoice->partial); + $this->assertNull($this->invoice->partial_due_date); + + $this->travelBack(); + + } + + + public function testMultiplePartialDueDateReminder() + { + + $settings = $this->company->settings; + $settings->enable_reminder1 = true; + $settings->schedule_reminder1 = 'before_due_date'; + $settings->num_days_reminder1 = 1; + $settings->enable_reminder2 = true; + $settings->schedule_reminder2 = 'after_due_date'; + $settings->num_days_reminder2 = 0; + $settings->enable_reminder3 = true; + $settings->schedule_reminder3 = 'after_due_date'; + $settings->num_days_reminder3 = 7; + $settings->timezone_id = '29'; + $settings->entity_send_time = 0; + $settings->endless_reminder_frequency_id = ''; + $settings->enable_reminder_endless = false; + + $this->buildData(($settings)); + + $this->invoice->reminder1_sent = null; + $this->invoice->reminder2_sent = null; + $this->invoice->reminder3_sent = null; + $this->invoice->date = now()->startOfDay(); + $this->invoice->partial = 10; + $this->invoice->amount = 100; + $this->invoice->balance = 100; + $this->invoice->partial_due_date = now()->startOfDay()->addDays(7); + $this->invoice->due_date = now()->startOfDay()->addMonth(); + $this->invoice->service()->setReminder($settings)->save(); + + $this->invoice = $this->invoice->fresh(); + + $this->assertEquals(now()->startOfDay()->addDays(6)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d')); + $this->assertTrue($this->invoice->hasPartial()); + + // nlog("partial due date = {$this->invoice->partial_due_date}"); + // nlog("due date = {$this->invoice->due_date}"); + // nlog("travelling to: ". Carbon::parse($this->invoice->partial_due_date)->subDay()->addHour()->startOfDay()->format("Y-m-d")); + // nlog("Reminder 1 test"); + + $this->travelTo(Carbon::parse($this->invoice->partial_due_date)->subDay()->addHours(2)->startOfDay()); + (new ReminderJob())->handle(); + + $this->invoice = $this->invoice->fresh(); + $this->assertEquals(now()->format('Y-m-d'), Carbon::parse($this->invoice->reminder_last_sent)->format('Y-m-d')); + $this->assertNotNull($this->invoice->reminder1_sent); + $this->assertEquals(Carbon::parse($this->invoice->partial_due_date)->startOfDay()->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d')); + + $this->travelTo(Carbon::parse($this->invoice->partial_due_date)->startOfDay()); + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertEquals(now()->format('Y-m-d'), Carbon::parse($this->invoice->reminder_last_sent)->format('Y-m-d')); + $this->assertNotNull($this->invoice->reminder2_sent); + $this->assertEquals(Carbon::parse($this->invoice->partial_due_date)->startOfDay()->addDays(7)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d')); + + // nlog("travelling to: ".Carbon::parse($this->invoice->partial_due_date)->addDays(7)->startOfDay()->format('Y-m-d')); + + $this->travelTo(Carbon::parse($this->invoice->partial_due_date)->addDays(7)->startOfDay()); + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertEquals(now()->format('Y-m-d'), Carbon::parse($this->invoice->reminder_last_sent)->format('Y-m-d')); + $this->assertNotNull($this->invoice->reminder3_sent); + $this->assertNull($this->invoice->next_send_date); + + $this->invoice->service()->applyPaymentAmount(10)->save(); + $this->invoice = $this->invoice->fresh(); + + /** Iterate through Due Date Reminders now */ + $this->assertEquals(0, $this->invoice->partial); + $this->assertNull($this->invoice->partial_due_date); + $this->assertEquals(Carbon::parse($this->invoice->due_date)->subDay()->startOfDay(), Carbon::parse($this->invoice->next_send_date)); + + $this->travelTo(Carbon::parse($this->invoice->due_date)->subDay()->startOfDay()->addHour()); + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + + $this->assertNotNull($this->invoice->reminder1_sent); + $this->assertEquals(Carbon::parse($this->invoice->due_date)->subDay()->startOfDay(), Carbon::parse($this->invoice->reminder_last_sent)->startOfDay()); + + $this->travelTo(Carbon::parse($this->invoice->due_date)->startOfDay()->addHour()); + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertNotNull($this->invoice->reminder2_sent); + $this->assertEquals(Carbon::parse($this->invoice->due_date)->startOfDay(), Carbon::parse($this->invoice->reminder_last_sent)->startOfDay()); + $this->assertEquals(Carbon::parse($this->invoice->due_date)->addDays(7)->startOfDay(), Carbon::parse($this->invoice->next_send_date)); + + $this->travelTo(Carbon::parse($this->invoice->due_date)->addDays(7)->startOfDay()->addHour()); + (new ReminderJob())->handle(); + $this->invoice = $this->invoice->fresh(); + $this->assertNotNull($this->invoice->reminder3_sent); + $this->assertEquals(now()->startOfDay(), Carbon::parse($this->invoice->reminder_last_sent)->startOfDay()); + $this->assertNull($this->invoice->next_send_date); + + $this->travelBack(); + + } + + public function testPartialDueDateReminder() {