format('Y-m-d h:i:s')); Quote::query() ->where('quotes.is_deleted', 0) ->whereIn('quotes.status_id', [Invoice::STATUS_SENT]) ->whereNull('quotes.deleted_at') ->where('quotes.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); // }) ->leftJoin('clients', function ($join) { $join->on('quotes.client_id', '=', 'clients.id') ->where('clients.is_deleted', 0) ->whereNull('clients.deleted_at'); }) ->leftJoin('companies', function ($join) { $join->on('quotes.company_id', '=', 'companies.id') ->where('companies.is_disabled', 0); }) ->with('invitations')->chunk(50, function ($quotes) { foreach ($quotes as $quote) { $this->sendReminderForQuote($quote); } sleep(1); }); } else { //multiDB environment, need to foreach (MultiDB::$dbs as $db) { MultiDB::setDB($db); nrlog("Sending quote reminders on db {$db} ".now()->format('Y-m-d h:i:s')); Quote::query() ->where('quotes.is_deleted', 0) ->whereIn('quotes.status_id', [Invoice::STATUS_SENT]) ->whereNull('quotes.deleted_at') ->where('quotes.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); // }) ->leftJoin('clients', function ($join) { $join->on('quotes.client_id', '=', 'clients.id') ->where('clients.is_deleted', 0) ->whereNull('clients.deleted_at'); }) ->leftJoin('companies', function ($join) { $join->on('quotes.company_id', '=', 'companies.id') ->where('companies.is_disabled', 0); }) ->with('invitations')->chunk(50, function ($quotes) { foreach ($quotes as $quote) { $this->sendReminderForQuote($quote); } sleep(1); }); } } } private function sendReminderForQuote(Quote $quote) { App::forgetInstance('translator'); $t = app('translator'); $t->replace(Ninja::transformTranslations($quote->client->getMergedSettings())); App::setLocale($quote->client->locale()); if ($quote->isPayable()) { //Attempts to prevent duplicates from sending if ($quote->reminder_last_sent && Carbon::parse($quote->reminder_last_sent)->startOfDay()->eq(now()->startOfDay())) { nrlog("caught a duplicate reminder for quote {$quote->number}"); return; } $reminder_template = $quote->calculateTemplate('quote'); nrlog("#{$quote->number} => reminder template = {$reminder_template}"); $quote->service()->touchReminder($reminder_template)->save(); //20-04-2022 fixes for endless reminders - generic template naming was wrong $enabled_reminder = 'enable_quote_'.$reminder_template; // if ($reminder_template == 'endless_reminder') { // $enabled_reminder = 'enable_reminder_endless'; // } if (in_array($reminder_template, ['reminder1', 'reminder2', 'reminder3', 'reminder_endless', 'endless_reminder']) && $quote->client->getSetting($enabled_reminder) && $quote->client->getSetting('send_reminders') && (Ninja::isSelfHost() || $quote->company->account->isPaidHostedClient())) { $quote->invitations->each(function ($invitation) use ($quote, $reminder_template) { if ($invitation->contact && !$invitation->contact->trashed() && $invitation->contact->email) { EmailEntity::dispatch($invitation, $invitation->company, $reminder_template); nrlog("Firing reminder email for quote {$quote->number} - {$reminder_template}"); $quote->entityEmailEvent($invitation, $reminder_template); $quote->sendEvent(Webhook::EVENT_REMIND_QUOTE, "client"); } }); } $quote->service()->setReminder()->save(); } else { $quote->next_send_date = null; $quote->save(); } } }