diff --git a/app/Console/Commands/SendRemindersCron.php b/app/Console/Commands/SendRemindersCron.php index 098f1b032b57..1c578c2c4aaa 100644 --- a/app/Console/Commands/SendRemindersCron.php +++ b/app/Console/Commands/SendRemindersCron.php @@ -62,17 +62,29 @@ class SendRemindersCron extends Command public function handle() { Invoice::where('next_send_date', '<=', now()->toDateTimeString()) - ->whereNull('deleted_at') - ->where('is_deleted', 0) - ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) - ->where('balance', '>', 0) - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); - }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); - }) + ->whereNull('invoices.deleted_at') + ->where('invoices.is_deleted', 0) + ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->where('invoices.balance', '>', 0) + + ->leftJoin('clients', function ($join) { + $join->on('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); + }) + ->leftJoin('companies', function ($join) { + $join->on('invoices.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); + }) + + // ->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->isPayable()) { $reminder_template = $invoice->calculateTemplate('invoice'); diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index 143c96e1d7cc..d7d605d3d8ac 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -282,9 +282,11 @@ abstract class QueryFilters if($value == 'true') { return $this->builder->leftJoin('clients', function($join) { - $join->on('invoices.client_id', '=', 'clients.id') - ->where('clients.is_deleted', 0) - ->whereNull('clients.deleted_at'); + + $join->on("{$this->builder->getQuery()->from}.client_id", '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); + }); } diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 50b0c46cf58e..5cf35adef3c2 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -81,14 +81,20 @@ class SearchController extends Controller $invoices = Invoice::query() ->company() ->with('client') - ->where('is_deleted', 0) - ->whereHas('client', function ($q) { - $q->where('is_deleted', 0); - }) + ->where('invoices.is_deleted', 0) + // ->whereHas('client', function ($q) { + // $q->where('is_deleted', 0); + // }) + + ->leftJoin('clients', function ($join) { + $join->on('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0); + }) + ->when(!$user->hasPermission('view_all') || !$user->hasPermission('view_invoice'), function ($query) use ($user) { - $query->where('user_id', $user->id); + $query->where('invoices.user_id', $user->id); }) - ->orderBy('id', 'desc') + ->orderBy('invoices.id', 'desc') ->take(3000) ->get(); diff --git a/app/Jobs/Cron/RecurringInvoicesCron.php b/app/Jobs/Cron/RecurringInvoicesCron.php index f295ea6e446b..8c32e62b5c2f 100644 --- a/app/Jobs/Cron/RecurringInvoicesCron.php +++ b/app/Jobs/Cron/RecurringInvoicesCron.php @@ -48,18 +48,27 @@ class RecurringInvoicesCron Auth::logout(); if (! config('ninja.db.multi_db_enabled')) { - $recurring_invoices = RecurringInvoice::query()->where('status_id', RecurringInvoice::STATUS_ACTIVE) - ->where('is_deleted', false) - ->where('remaining_cycles', '!=', '0') - ->whereNotNull('next_send_date') - ->whereNull('deleted_at') - ->where('next_send_date', '<=', now()->toDateTimeString()) - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); + $recurring_invoices = RecurringInvoice::query()->where('recurring_invoices.status_id', RecurringInvoice::STATUS_ACTIVE) + ->where('recurring_invoices.is_deleted', false) + ->where('recurring_invoices.remaining_cycles', '!=', '0') + ->whereNotNull('recurring_invoices.next_send_date') + ->whereNull('recurring_invoices.deleted_at') + ->where('recurring_invoices.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('recurring_invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); + ->leftJoin('companies', function ($join) { + $join->on('recurring_invoices.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); }) ->with('company') ->cursor(); @@ -87,18 +96,27 @@ class RecurringInvoicesCron foreach (MultiDB::$dbs as $db) { MultiDB::setDB($db); - $recurring_invoices = RecurringInvoice::query()->where('status_id', RecurringInvoice::STATUS_ACTIVE) - ->where('is_deleted', false) - ->where('remaining_cycles', '!=', '0') - ->whereNull('deleted_at') - ->whereNotNull('next_send_date') - ->where('next_send_date', '<=', now()->toDateTimeString()) - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); + $recurring_invoices = RecurringInvoice::query()->where('recurring_invoices.status_id', RecurringInvoice::STATUS_ACTIVE) + ->where('recurring_invoices.is_deleted', false) + ->where('recurring_invoices.remaining_cycles', '!=', '0') + ->whereNull('recurring_invoices.deleted_at') + ->whereNotNull('recurring_invoices.next_send_date') + ->where('recurring_invoices.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('recurring_invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); + ->leftJoin('companies', function ($join) { + $join->on('recurring_invoices.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); }) ->with('company') ->cursor(); diff --git a/app/Jobs/Invoice/InvoiceCheckLateWebhook.php b/app/Jobs/Invoice/InvoiceCheckLateWebhook.php index 50576ac642d5..4e036657f96c 100644 --- a/app/Jobs/Invoice/InvoiceCheckLateWebhook.php +++ b/app/Jobs/Invoice/InvoiceCheckLateWebhook.php @@ -51,20 +51,29 @@ class InvoiceCheckLateWebhook implements ShouldQueue ->pluck('company_id'); Invoice::query() - ->where('is_deleted', false) - ->whereNull('deleted_at') - ->whereNotNull('due_date') - ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) - ->where('balance', '>', 0) - ->whereIn('company_id', $company_ids) - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); - }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); - }) - ->whereBetween('due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) + ->where('invoices.is_deleted', false) + ->whereNull('invoices.deleted_at') + ->whereNotNull('invoices.due_date') + ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->where('invoices.balance', '>', 0) + ->whereIn('invoices.company_id', $company_ids) + // ->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('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); + }) + ->leftJoin('companies', function ($join) { + $join->on('invoices.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); + }) + ->whereBetween('invoices.due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) ->cursor() ->each(function ($invoice) { (new WebhookHandler(Webhook::EVENT_LATE_INVOICE, $invoice, $invoice->company, 'client'))->handle(); @@ -78,20 +87,29 @@ class InvoiceCheckLateWebhook implements ShouldQueue ->pluck('company_id'); Invoice::query() - ->where('is_deleted', false) - ->whereNull('deleted_at') - ->whereNotNull('due_date') - ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) - ->where('balance', '>', 0) - ->whereIn('company_id', $company_ids) - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); - }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); - }) - ->whereBetween('due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) + ->where('invoices.is_deleted', false) + ->whereNull('invoices.deleted_at') + ->whereNotNull('invoices.due_date') + ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->where('invoices.balance', '>', 0) + ->whereIn('invoices.company_id', $company_ids) + // ->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('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); + }) + ->leftJoin('companies', function ($join) { + $join->on('invoices.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); + }) + ->whereBetween('invoices.due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) ->cursor() ->each(function ($invoice) { (new WebhookHandler(Webhook::EVENT_LATE_INVOICE, $invoice, $invoice->company, 'client'))->handle(); diff --git a/app/Jobs/Quote/QuoteCheckExpired.php b/app/Jobs/Quote/QuoteCheckExpired.php index 8082936b58dc..9e6f278d359d 100644 --- a/app/Jobs/Quote/QuoteCheckExpired.php +++ b/app/Jobs/Quote/QuoteCheckExpired.php @@ -49,19 +49,28 @@ class QuoteCheckExpired implements ShouldQueue { if (! config('ninja.db.multi_db_enabled')) { Quote::query() - ->where('status_id', Quote::STATUS_SENT) - ->where('is_deleted', false) - ->whereNull('deleted_at') - ->whereNotNull('due_date') - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); - }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); - }) - // ->where('due_date', '<='. now()->toDateTimeString()) - ->whereBetween('due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) + ->where('quotes.status_id', Quote::STATUS_SENT) + ->where('quotes.is_deleted', false) + ->whereNull('quotes.deleted_at') + ->whereNotNull('quotes.due_date') + // ->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); + }) + + ->whereBetween('quotes.due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) ->cursor() ->each(function ($quote) { $this->queueExpiredQuoteNotification($quote); @@ -71,19 +80,27 @@ class QuoteCheckExpired implements ShouldQueue MultiDB::setDB($db); Quote::query() - ->where('status_id', Quote::STATUS_SENT) - ->where('is_deleted', false) - ->whereNull('deleted_at') - ->whereNotNull('due_date') - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0) - ->where('deleted_at', null); + ->where('quotes.status_id', Quote::STATUS_SENT) + ->where('quotes.is_deleted', false) + ->whereNull('quotes.deleted_at') + ->whereNotNull('quotes.due_date') + // ->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'); }) - ->whereHas('company', function ($query) { - $query->where('is_disabled', 0); - }) - // ->where('due_date', '<='. now()->toDateTimeString()) - ->whereBetween('due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) + ->leftJoin('companies', function ($join) { + $join->on('quotes.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); + }) + ->whereBetween('quotes.due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) ->cursor() ->each(function ($quote) { $this->queueExpiredQuoteNotification($quote); diff --git a/app/Jobs/Util/QuoteReminderJob.php b/app/Jobs/Util/QuoteReminderJob.php index ed1aa5fa722a..2df9da34f469 100644 --- a/app/Jobs/Util/QuoteReminderJob.php +++ b/app/Jobs/Util/QuoteReminderJob.php @@ -61,17 +61,26 @@ class QuoteReminderJob implements ShouldQueue nrlog("Sending quote reminders on ".now()->format('Y-m-d h:i:s')); Quote::query() - ->where('is_deleted', 0) - ->whereIn('status_id', [Invoice::STATUS_SENT]) - ->whereNull('deleted_at') - ->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); - }) + ->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); @@ -88,17 +97,26 @@ class QuoteReminderJob implements ShouldQueue nrlog("Sending quote reminders on db {$db} ".now()->format('Y-m-d h:i:s')); Quote::query() - ->where('is_deleted', 0) - ->whereIn('status_id', [Invoice::STATUS_SENT]) - ->whereNull('deleted_at') - ->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); - }) + ->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) { diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index 38b2009c4b2f..0ce65c34d531 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -59,18 +59,27 @@ class ReminderJob implements ShouldQueue nrlog("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); - }) + ->where('invoices.is_deleted', 0) + ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->whereNull('invoices.deleted_at') + ->where('invoices.balance', '>', 0) + ->where('invoices.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('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); + }) + ->leftJoin('companies', function ($join) { + $join->on('invoices.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); + }) ->with('invitations')->chunk(50, function ($invoices) { foreach ($invoices as $invoice) { $this->sendReminderForInvoice($invoice); @@ -87,18 +96,27 @@ class ReminderJob implements ShouldQueue nrlog("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); - }) + ->where('invoices.is_deleted', 0) + ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->whereNull('invoices.deleted_at') + ->where('invoices.balance', '>', 0) + ->where('invoices.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('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); + }) + ->leftJoin('companies', function ($join) { + $join->on('invoices.company_id', '=', 'companies.id') + ->where('companies.is_disabled', 0); + }) ->with('invitations')->chunk(50, function ($invoices) { foreach ($invoices as $invoice) { diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 065e3c577cb2..fbe763ee7f48 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -129,7 +129,19 @@ class BaseModel extends Model /** @var \App\Models\User $user */ $user = auth()->user(); - $query->where('company_id', $user->companyId()); + $query->where("{$query->getQuery()->from}.company_id", $user->companyId()); + + return $query; + } + + public function scopeWithoutDeletedClients($query) + { + + $query->leftJoin('clients', function ($join) use ($query){ + $join->on("{$query->getQuery()->from}.client_id", '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); + }); return $query; } diff --git a/app/Services/Report/ARDetailReport.php b/app/Services/Report/ARDetailReport.php index be8c83069936..c27b0e4308c9 100644 --- a/app/Services/Report/ARDetailReport.php +++ b/app/Services/Report/ARDetailReport.php @@ -90,15 +90,20 @@ class ARDetailReport extends BaseExport $this->csv->insertOne($this->buildHeader()); $query = Invoice::query() + ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) ->withTrashed() - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0); + // ->whereHas('client', function ($query) { + // $query->where('is_deleted', 0); + // }) + ->leftJoin('clients', function ($join) { + $join->on('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); }) - ->where('company_id', $this->company->id) - ->where('is_deleted', 0) - ->where('balance', '>', 0) - ->orderBy('due_date', 'ASC') - ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]); + ->where('invoices.company_id', $this->company->id) + ->where('invoices.is_deleted', 0) + ->where('invoices.balance', '>', 0) + ->orderBy('invoices.due_date', 'ASC'); $query = $this->addDateRange($query, 'invoices'); diff --git a/app/Services/Report/ProfitLoss.php b/app/Services/Report/ProfitLoss.php index 09d392435a12..c921df0f187e 100644 --- a/app/Services/Report/ProfitLoss.php +++ b/app/Services/Report/ProfitLoss.php @@ -265,8 +265,13 @@ class ProfitLoss ->whereIn('status_id', [1, 4, 5]) ->where('is_deleted', 0) ->whereBetween('date', [$this->start_date, $this->end_date]) - ->whereHas('client', function ($query) { - $query->where('is_deleted', 0); + // ->whereHas('client', function ($query) { + // $query->where('is_deleted', 0); + // }) + ->leftJoin('clients', function ($join) { + $join->on('payments.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); }) ->with(['company', 'client']) ->cursor()