Updates for subscription cron logic to utilize company timezone

This commit is contained in:
David Bomba 2024-04-02 12:06:20 +11:00
parent dd28cb0372
commit d353bfc52a
2 changed files with 257 additions and 44 deletions

View File

@ -39,62 +39,25 @@ class SubscriptionCron
*/
public function handle(): void
{
nlog('Subscription Cron');
Auth::logout();
if (! config('ninja.db.multi_db_enabled')) {
$invoices = Invoice::where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('balance', '>', 0)
->where('is_proforma', 0)
->whereDate('due_date', '<=', now()->addDay()->startOfDay())
->whereNull('deleted_at')
->whereNotNull('subscription_id')
->cursor();
$invoices->each(function (Invoice $invoice) {
$subscription = $invoice->subscription;
nlog('Subscription Cron '. now()->toDateTimeString());
$body = [
'context' => 'plan_expired',
'client' => $invoice->client->hashed_id,
'invoice' => $invoice->hashed_id,
'subscription' => $subscription->hashed_id,
];
$this->timezoneAware();
$this->sendLoad($subscription, $body);
//This will send the notification daily.
//We'll need to handle this by performing some action on the invoice to either archive it or delete it?
});
} else {
//multiDB environment, need to
foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db);
$invoices = Invoice::where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('balance', '>', 0)
->where('is_proforma', 0)
->whereDate('due_date', '<=', now()->addDay()->startOfDay())
->whereNull('deleted_at')
->whereNotNull('subscription_id')
->cursor();
nlog('Subscription Cron for ' . $db . ' ' . now()->toDateTimeString());
$invoices->each(function (Invoice $invoice) {
$subscription = $invoice->subscription;
$this->timezoneAware();
$body = [
'context' => 'plan_expired',
'client' => $invoice->client->hashed_id,
'invoice' => $invoice->hashed_id,
'subscription' => $subscription->hashed_id,
];
$this->sendLoad($subscription, $body);
//This will send the notification daily.
//We'll need to handle this by performing some action on the invoice to either archive it or delete it?
});
}
}
}
@ -131,7 +94,7 @@ class SubscriptionCron
->where('is_proforma', 0)
->whereNotNull('subscription_id')
->where('balance', '>', 0)
->whereDate('due_date', '<=', now()->setTimezone($company->timezone()->name)->addDay()->startOfDay())
->whereDate('due_date', '<=', now()->addDay()->startOfDay())
->cursor()
->each(function (Invoice $invoice) {

View File

@ -12,13 +12,19 @@
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use App\Models\Client;
use App\Models\Company;
use App\Models\Invoice;
use App\Models\Product;
use App\Models\RecurringInvoice;
use Tests\MockAccountData;
use Illuminate\Support\Str;
use App\Models\CompanyToken;
use App\Models\Subscription;
use App\Utils\Traits\MakesHash;
use App\Models\RecurringInvoice;
use App\DataMapper\CompanySettings;
use App\Factory\CompanyUserFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\ValidationException;
@ -51,6 +57,250 @@ class SubscriptionApiTest extends TestCase
Model::reguard();
}
public function testSubscriptionCronLocalization()
{
$settings = CompanySettings::defaults();
$settings->timezone_id = '50'; //europe/vienna
$c2 = Company::factory()->create([
'account_id' => $this->company->account_id,
'settings' => $settings
]);
$cu = CompanyUserFactory::create($this->user->id, $c2->id, $this->account->id);
$cu->is_owner = true;
$cu->is_admin = true;
$cu->is_locked = true;
$cu->permissions = '["view_client"]';
$cu->save();
$different_company_token = \Illuminate\Support\Str::random(64);
$company_token = new CompanyToken();
$company_token->user_id = $this->user->id;
$company_token->company_id = $c2->id;
$company_token->account_id = $c2->account_id;
$company_token->name = 'test token';
$company_token->token = $different_company_token;
$company_token->is_system = true;
$company_token->save();
$s = Subscription::factory()->create([
'company_id' => $c2->id,
'user_id' => $this->user->id,
]);
$client2 = Client::factory()->create([
'company_id' => $c2->id,
'user_id' => $this->user->id,
]);
$i = Invoice::factory()->create([
'company_id' => $c2->id,
'user_id' => $this->user->id,
'subscription_id' => $s->id,
'due_date' => now()->startOfDay(),
'client_id' => $client2->id,
'status_id' => Invoice::STATUS_SENT
]);
$settings = CompanySettings::defaults();
$settings->timezone_id = '110'; //sydney/australia
$c = Company::factory()->create([
'account_id' => $this->company->account_id,
'settings' => $settings,
]);
$cu = CompanyUserFactory::create($this->user->id, $c->id, $this->account->id);
$cu->is_owner = true;
$cu->is_admin = true;
$cu->is_locked = true;
$cu->permissions = '["view_client"]';
$cu->save();
$different_company_token = \Illuminate\Support\Str::random(64);
$company_token = new CompanyToken();
$company_token->user_id = $this->user->id;
$company_token->company_id = $c->id;
$company_token->account_id = $c->account_id;
$company_token->name = 'test token';
$company_token->token = $different_company_token;
$company_token->is_system = true;
$company_token->save();
$s1 = Subscription::factory()->create([
'company_id' => $c->id,
'user_id' => $this->user->id,
]);
$client = Client::factory()->create([
'company_id' => $c2->id,
'user_id' => $this->user->id,
]);
$i = Invoice::factory()->create([
'company_id' => $c->id,
'user_id' => $this->user->id,
'subscription_id' => $s1->id,
'due_date' => now()->startOfDay(),
'client_id' => $client->id,
'status_id' => Invoice::STATUS_SENT
]);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
$company = Company::find($c->id); //sydney
$timezone_now = now()->setTimezone($company->timezone()->name);
$this->assertEquals('Australia/Sydney', $timezone_now->timezoneName);
$this->travelTo($timezone_now->copy()->startOfDay()->subHour());
$i = false;
//Capture companies within the window of 00:00 and 00:30
if($timezone_now->gte($timezone_now->copy()->startOfDay()) && $timezone_now->lt($timezone_now->copy()->startOfDay()->addMinutes(30))) {
$i = Invoice::query()
->where('company_id', $company->id)
->whereNull('deleted_at')
->where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('is_proforma', 0)
->whereNotNull('subscription_id')
->where('balance', '>', 0)
->whereDate('due_date', '<=', now()->setTimezone($company->timezone()->name)->addDay()->startOfDay())
->get();
}
$this->assertFalse($i);
$this->travelTo($timezone_now->copy()->startOfDay());
if(now()->gte($timezone_now->copy()->startOfDay()) && now()->lt($timezone_now->copy()->startOfDay()->addMinutes(30))) {
$i = Invoice::query()
->where('company_id', $company->id)
->whereNull('deleted_at')
->where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('is_proforma', 0)
->whereNotNull('subscription_id')
->whereDate('due_date', '<=', now()->setTimezone($company->timezone()->name)->addDay()->startOfDay())
->get();
}
$this->assertEquals(1, $i->count());
$i = false;
$this->travelTo($timezone_now->copy()->startOfDay()->addHours(2));
if($timezone_now->gte($timezone_now->copy()->startOfDay()) && $timezone_now->lt($timezone_now->copy()->startOfDay()->addMinutes(30))) {
$i = Invoice::query()
->where('company_id', $company->id)
->whereNull('deleted_at')
->where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('is_proforma', 0)
->whereNotNull('subscription_id')
->where('balance', '>', 0)
->whereDate('due_date', '<=', now()->setTimezone($company->timezone()->name)->addDay()->startOfDay())
->get();
}
$this->assertFalse($i);
$count = Invoice::whereNotNull('subscription_id')->count();
$this->assertEquals(2, $count);
$this->travelBack();
//////////////////////////////////////////// vienna //////////////////////////////////////////////////
$company = Company::find($c2->id); //vienna
$timezone_now = now()->setTimezone($company->timezone()->name);
$this->assertEquals('Europe/Vienna', $timezone_now->timezoneName);
$this->travelTo($timezone_now->copy()->startOfDay()->subHour());
$this->travelTo($timezone_now->copy()->startOfDay()->subHour());
$i = false;
//Capture companies within the window of 00:00 and 00:30
if($timezone_now->gte($timezone_now->copy()->startOfDay()) && $timezone_now->lt($timezone_now->copy()->startOfDay()->addMinutes(30))) {
$i = Invoice::query()
->where('company_id', $company->id)
->whereNull('deleted_at')
->where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('is_proforma', 0)
->whereNotNull('subscription_id')
->where('balance', '>', 0)
->whereDate('due_date', '<=', now()->setTimezone($company->timezone()->name)->addDay()->startOfDay())
->get();
}
$this->assertFalse($i);
$this->travelTo($timezone_now->copy()->startOfDay());
if(now()->gte($timezone_now->copy()->startOfDay()) && now()->lt($timezone_now->copy()->startOfDay()->addMinutes(30))) {
$i = Invoice::query()
->where('company_id', $company->id)
->whereNull('deleted_at')
->where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('is_proforma', 0)
->whereNotNull('subscription_id')
->whereDate('due_date', '<=', now()->setTimezone($company->timezone()->name)->addDay()->startOfDay())
->get();
}
$this->assertEquals(1, $i->count());
$i = false;
$this->travelTo($timezone_now->copy()->startOfDay()->addHours(2));
if($timezone_now->gte($timezone_now->copy()->startOfDay()) && $timezone_now->lt($timezone_now->copy()->startOfDay()->addMinutes(30))) {
$i = Invoice::query()
->where('company_id', $company->id)
->whereNull('deleted_at')
->where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('is_proforma', 0)
->whereNotNull('subscription_id')
->where('balance', '>', 0)
->whereDate('due_date', '<=', now()->setTimezone($company->timezone()->name)->addDay()->startOfDay())
->get();
}
$this->assertFalse($i);
}
public function testAssignInvoice()
{
$i = Invoice::factory()