diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 0aa9dcb2a991..9beaefda8822 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -105,11 +105,11 @@ class Kernel extends ConsoleKernel //not used @deprecate // $schedule->job(new SendFailedEmails)->daily()->withoutOverlapping(); - $schedule->command('ninja:check-data --database=db-ninja-01')->daily('02:00')->withoutOverlapping(); + $schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer(); - $schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:05')->withoutOverlapping(); + $schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:20')->withoutOverlapping()->name('check-data-db-2-job')->onOneServer(); - $schedule->command('ninja:s3-cleanup')->dailyAt('23:15')->withoutOverlapping(); + $schedule->command('ninja:s3-cleanup')->dailyAt('23:15')->withoutOverlapping()->name('s3-cleanup-job')->onOneServer(); } diff --git a/app/Jobs/Cron/SubscriptionCron.php b/app/Jobs/Cron/SubscriptionCron.php index b3e14f140d2d..1242a63cbc08 100644 --- a/app/Jobs/Cron/SubscriptionCron.php +++ b/app/Jobs/Cron/SubscriptionCron.php @@ -41,44 +41,62 @@ class SubscriptionCron nlog('Subscription Cron'); if (! config('ninja.db.multi_db_enabled')) { - $this->loopSubscriptions(); + + $invoices = Invoice::where('is_deleted', 0) + ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->where('balance', '>', 0) + ->whereDate('due_date', '<=', now()->addDay()->startOfDay()) + ->whereNull('deleted_at') + ->whereNotNull('subscription_id') + ->cursor(); + + $invoices->each(function ($invoice) { + $subscription = $invoice->subscription; + + $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? + }); + + } else { //multiDB environment, need to foreach (MultiDB::$dbs as $db) { MultiDB::setDB($db); - $this->loopSubscriptions(); + $invoices = Invoice::where('is_deleted', 0) + ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->where('balance', '>', 0) + ->whereDate('due_date', '<=', now()->addDay()->startOfDay()) + ->whereNull('deleted_at') + ->whereNotNull('subscription_id') + ->cursor(); + + $invoices->each(function ($invoice) { + $subscription = $invoice->subscription; + + $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? + }); + + } } } - private function loopSubscriptions() - { - $invoices = Invoice::where('is_deleted', 0) - ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) - ->where('balance', '>', 0) - ->whereDate('due_date', '<=', now()->addDay()->startOfDay()) - ->whereNull('deleted_at') - ->whereNotNull('subscription_id') - ->cursor(); - - $invoices->each(function ($invoice) { - $subscription = $invoice->subscription; - - $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? - }); - } - - private function handleWebhook($invoice, $subscription) - { - } } diff --git a/app/Jobs/Ninja/CompanySizeCheck.php b/app/Jobs/Ninja/CompanySizeCheck.php index c47d3cb65233..a282d1e7166c 100644 --- a/app/Jobs/Ninja/CompanySizeCheck.php +++ b/app/Jobs/Ninja/CompanySizeCheck.php @@ -42,39 +42,54 @@ class CompanySizeCheck implements ShouldQueue public function handle() { if (! config('ninja.db.multi_db_enabled')) { - $this->check(); + + Company::where('is_large', false)->withCount(['invoices', 'clients', 'products'])->cursor()->each(function ($company) { + if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500) { + nlog("Marking company {$company->id} as large"); + + $company->account->companies()->update(['is_large' => true]); + } + }); + + nlog("updating all client credit balances"); + + Client::where('updated_at', '>', now()->subDay()) + ->cursor() + ->each(function ($client){ + + $client->credit_balance = $client->service()->getCreditBalance(); + $client->save(); + + }); + } else { //multiDB environment, need to foreach (MultiDB::$dbs as $db) { MultiDB::setDB($db); - $this->check(); + nlog("Company size check db {$db}"); + + Company::where('is_large', false)->withCount(['invoices', 'clients', 'products'])->cursor()->each(function ($company) { + if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500) { + nlog("Marking company {$company->id} as large"); + + $company->account->companies()->update(['is_large' => true]); + } + }); + + nlog("updating all client credit balances"); + + Client::where('updated_at', '>', now()->subDay()) + ->cursor() + ->each(function ($client){ + + $client->credit_balance = $client->service()->getCreditBalance(); + $client->save(); + + }); + } } } - private function check() - { - nlog("Checking all company sizes"); - - Company::where('is_large', false)->withCount(['invoices', 'clients', 'products'])->cursor()->each(function ($company) { - if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500) { - nlog("Marking company {$company->id} as large"); - - $company->account->companies()->update(['is_large' => true]); - } - }); - - nlog("updating all client credit balances"); - - Client::where('updated_at', '>', now()->subDay()) - ->cursor() - ->each(function ($client){ - - $client->credit_balance = $client->service()->getCreditBalance(); - $client->save(); - - }); - - } } diff --git a/app/Jobs/Ninja/QueueSize.php b/app/Jobs/Ninja/QueueSize.php index 3503f5312438..ce155c63db65 100644 --- a/app/Jobs/Ninja/QueueSize.php +++ b/app/Jobs/Ninja/QueueSize.php @@ -40,7 +40,7 @@ class QueueSize implements ShouldQueue * * @return void */ - public function handle() + public function handle() :void { LightLogs::create(new QueueSizeAnalytic(Queue::size())) ->send(); diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index eb609e2287b2..379b7ab46a85 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -46,83 +46,110 @@ class ReminderJob implements ShouldQueue */ public function handle() :void { - if (! config('ninja.db.multi_db_enabled')) { - $this->processReminders(); + if (! config('ninja.db.multi_db_enabled')) + { + set_time_limit(0); + + nlog("Sending invoice reminders on ".now()->format('Y-m-d h:i:s')); + + Invoice::query() + ->where('is_deleted', 0) + ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->whereNull('deleted_at') + ->where('balance', '>', 0) + ->where('next_send_date', '<=', now()->toDateTimeString()) + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0) + ->where('deleted_at', null); + }) + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0); + }) + ->with('invitations')->cursor()->each(function ($invoice) { + + $this->sendReminderForInvoice($invoice); + + }); + + } else { //multiDB environment, need to - foreach (MultiDB::$dbs as $db) { + foreach (MultiDB::$dbs as $db) + { + MultiDB::setDB($db); - nlog("set db {$db}"); - $this->processReminders(); + + nlog("Sending invoice reminders on db {$db} ".now()->format('Y-m-d h:i:s')); + + Invoice::query() + ->where('is_deleted', 0) + ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->whereNull('deleted_at') + ->where('balance', '>', 0) + ->where('next_send_date', '<=', now()->toDateTimeString()) + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0) + ->where('deleted_at', null); + }) + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0); + }) + ->with('invitations')->cursor()->each(function ($invoice) { + // if ($invoice->refresh() && $invoice->isPayable()) { + + $this->sendReminderForInvoice($invoice); + + }); + } } } - private function processReminders() - { - nlog('Sending invoice reminders '.now()->format('Y-m-d h:i:s')); + private function sendReminderForInvoice($invoice) { - set_time_limit(0); + if ($invoice->isPayable()) { - Invoice::query() - ->where('is_deleted', 0) - ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) - ->whereNull('deleted_at') - ->where('balance', '>', 0) - ->where('next_send_date', '<=', now()->toDateTimeString()) - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); - }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); - }) - ->with('invitations')->cursor()->each(function ($invoice) { - // if ($invoice->refresh() && $invoice->isPayable()) { - if ($invoice->isPayable()) { + //Attempts to prevent duplicates from sending + if($invoice->reminder_last_sent && Carbon::parse($invoice->reminder_last_sent)->startOfDay()->eq(now()->startOfDay())){ + nlog("caught a duplicate reminder for invoice {$invoice->number}"); + return; + } - //Attempts to prevent duplicates from sending - if($invoice->reminder_last_sent && Carbon::parse($invoice->reminder_last_sent)->startOfDay()->eq(now()->startOfDay())){ - nlog("caught a duplicate reminder for invoice {$invoice->number}"); - return; - } + $reminder_template = $invoice->calculateTemplate('invoice'); + nlog("reminder template = {$reminder_template}"); + $invoice->service()->touchReminder($reminder_template)->save(); + $invoice = $this->calcLateFee($invoice, $reminder_template); - $reminder_template = $invoice->calculateTemplate('invoice'); - nlog("reminder template = {$reminder_template}"); - $invoice->service()->touchReminder($reminder_template)->save(); - $invoice = $this->calcLateFee($invoice, $reminder_template); + //20-04-2022 fixes for endless reminders - generic template naming was wrong + $enabled_reminder = 'enable_'.$reminder_template; + if ($reminder_template == 'endless_reminder') { + $enabled_reminder = 'enable_reminder_endless'; + } - //20-04-2022 fixes for endless reminders - generic template naming was wrong - $enabled_reminder = 'enable_'.$reminder_template; - if ($reminder_template == 'endless_reminder') { - $enabled_reminder = 'enable_reminder_endless'; - } + //check if this reminder needs to be emailed + //15-01-2022 - insert addition if block if send_reminders is definitely set + if (in_array($reminder_template, ['reminder1', 'reminder2', 'reminder3', 'reminder_endless', 'endless_reminder']) && + $invoice->client->getSetting($enabled_reminder) && + $invoice->client->getSetting('send_reminders') && + (Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) { - //check if this reminder needs to be emailed - //15-01-2022 - insert addition if block if send_reminders is definitely set - if (in_array($reminder_template, ['reminder1', 'reminder2', 'reminder3', 'reminder_endless', 'endless_reminder']) && - $invoice->client->getSetting($enabled_reminder) && - $invoice->client->getSetting('send_reminders') && - (Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) { + $invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) { + EmailEntity::dispatchSync($invitation, $invitation->company, $reminder_template); + nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}"); + }); - $invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) { - EmailEntity::dispatch($invitation, $invitation->company, $reminder_template); - nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}"); - }); - - if ($invoice->invitations->count() > 0) { - event(new InvoiceWasEmailed($invoice->invitations->first(), $invoice->company, Ninja::eventVars(), $reminder_template)); - } - } - $invoice->service()->setReminder()->save(); - } else { - $invoice->next_send_date = null; - $invoice->save(); + if ($invoice->invitations->count() > 0) { + event(new InvoiceWasEmailed($invoice->invitations->first(), $invoice->company, Ninja::eventVars(), $reminder_template)); } + } + $invoice->service()->setReminder()->save(); + } else { + $invoice->next_send_date = null; + $invoice->save(); + } - }); } /** diff --git a/app/Jobs/Util/UpdateExchangeRates.php b/app/Jobs/Util/UpdateExchangeRates.php index 4ff1ba8c48e6..57185ea5fb94 100644 --- a/app/Jobs/Util/UpdateExchangeRates.php +++ b/app/Jobs/Util/UpdateExchangeRates.php @@ -34,19 +34,7 @@ class UpdateExchangeRates implements ShouldQueue * * @return void */ - public function handle() - { - if (config('ninja.db.multi_db_enabled')) { - foreach (MultiDB::$dbs as $db) { - MultiDB::setDB($db); - $this->updateCurrencies(); - } - } else { - $this->updateCurrencies(); - } - } - - private function updateCurrencies() + public function handle() :void { info('updating currencies'); @@ -56,20 +44,47 @@ class UpdateExchangeRates implements ShouldQueue $cc_endpoint = sprintf('https://openexchangerates.org/api/latest.json?app_id=%s', config('ninja.currency_converter_api_key')); - $client = new Client(); - $response = $client->get($cc_endpoint); + if (config('ninja.db.multi_db_enabled')) { + foreach (MultiDB::$dbs as $db) { + MultiDB::setDB($db); + + $client = new Client(); + $response = $client->get($cc_endpoint); - $currency_api = json_decode($response->getBody()); + $currency_api = json_decode($response->getBody()); - /* Update all currencies */ - Currency::all()->each(function ($currency) use ($currency_api) { - $currency->exchange_rate = $currency_api->rates->{$currency->code}; - $currency->save(); - }); + /* Update all currencies */ + Currency::all()->each(function ($currency) use ($currency_api) { + $currency->exchange_rate = $currency_api->rates->{$currency->code}; + $currency->save(); + }); - /* Rebuild the cache */ - $currencies = Currency::orderBy('name')->get(); + /* Rebuild the cache */ + $currencies = Currency::orderBy('name')->get(); - Cache::forever('currencies', $currencies); + Cache::forever('currencies', $currencies); + + + } + } else { + + $client = new Client(); + $response = $client->get($cc_endpoint); + + $currency_api = json_decode($response->getBody()); + + /* Update all currencies */ + Currency::all()->each(function ($currency) use ($currency_api) { + $currency->exchange_rate = $currency_api->rates->{$currency->code}; + $currency->save(); + }); + + /* Rebuild the cache */ + $currencies = Currency::orderBy('name')->get(); + + Cache::forever('currencies', $currencies); + + } } + } diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index a79ccd9ab081..48c36cd9ff32 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -785,7 +785,7 @@ class SubscriptionService */ public function triggerWebhook($context) { - nlog("trigger webook"); + nlog("trigger webhook"); if (empty($this->subscription->webhook_configuration['post_purchase_url']) || is_null($this->subscription->webhook_configuration['post_purchase_url']) || strlen($this->subscription->webhook_configuration['post_purchase_url']) < 1) { return ["message" => "Success", "status_code" => 200];