From 96f980aa544cd70036d800cc3729886aa876b4a2 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 29 Jun 2024 09:00:36 +1000 Subject: [PATCH 1/8] Refactor for whereHas('client --- app/Console/Commands/SendRemindersCron.php | 34 ++++++--- app/Filters/QueryFilters.php | 8 ++- app/Http/Controllers/SearchController.php | 18 +++-- app/Jobs/Cron/RecurringInvoicesCron.php | 62 ++++++++++------ app/Jobs/Invoice/InvoiceCheckLateWebhook.php | 74 ++++++++++++-------- app/Jobs/Quote/QuoteCheckExpired.php | 67 +++++++++++------- app/Jobs/Util/QuoteReminderJob.php | 62 ++++++++++------ app/Jobs/Util/ReminderJob.php | 66 ++++++++++------- app/Models/BaseModel.php | 14 +++- app/Services/Report/ARDetailReport.php | 19 +++-- app/Services/Report/ProfitLoss.php | 9 ++- 11 files changed, 282 insertions(+), 151 deletions(-) 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() From 0d654dae952345d63132389f6e331a741e670241 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jul 2024 11:47:38 +1000 Subject: [PATCH 2/8] Fixes for tax map display of surcharge taxes --- app/Filters/InvoiceFilters.php | 2 +- app/Helpers/Invoice/InvoiceSumInclusive.php | 9 ++--- app/Repositories/ExpenseRepository.php | 3 +- tests/Feature/ExpenseApiTest.php | 38 +++++++++++++++++++++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 0343402a37b2..8567e9908344 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -320,7 +320,7 @@ class InvoiceFilters extends QueryFilters { $sort_col = explode('|', $sort); - if (!is_array($sort_col) || count($sort_col) != 2) { + if (!is_array($sort_col) || count($sort_col) != 2 || in_array($sort_col[0], ['documents'])) { return $this->builder; } diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index fe50d9cb1fb0..cb297250b273 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -74,8 +74,8 @@ class InvoiceSumInclusive { $this->calculateLineItems() ->calculateDiscount() - ->calculateInvoiceTaxes() - ->calculateCustomValues() + ->calculateCustomValues() //06-07-2024 + ->calculateInvoiceTaxes() //shuffle order of invoicetaxes/custom values to include the surcharge taxes in the tax map ->setTaxMap() ->calculateTotals() //just don't add the taxes!! ->calculateBalance() @@ -119,8 +119,6 @@ class InvoiceSumInclusive $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge4, $this->invoice->custom_surcharge_tax4); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge4); - $this->total += $this->total_custom_values; - return $this; } @@ -172,6 +170,8 @@ class InvoiceSumInclusive $this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.floatval($this->invoice->tax_rate3).'%', 'total' => $tax]; } + $this->total += $this->total_custom_values; //06-07-2024 add the custom surcharge totals here after the tax calculations. + return $this; } @@ -395,4 +395,5 @@ class InvoiceSumInclusive { return $this; } + } diff --git a/app/Repositories/ExpenseRepository.php b/app/Repositories/ExpenseRepository.php index 1bb055ecc733..ab83f2f80fb1 100644 --- a/app/Repositories/ExpenseRepository.php +++ b/app/Repositories/ExpenseRepository.php @@ -47,11 +47,10 @@ class ExpenseRepository extends BaseRepository $user = auth()->user(); $payment_date = &$data['payment_date']; - $vendor_id = &$data['vendor_id']; if($payment_date && $payment_date == $expense->payment_date) { //do nothing - } elseif($payment_date && strlen($payment_date) > 1 && $user->company()->notify_vendor_when_paid && ($vendor_id || $expense->vendor_id)) { + } elseif($payment_date && strlen($payment_date) > 1 && $user->company()->notify_vendor_when_paid && (isset($data['vendor_id']) || $expense->vendor_id)) { $this->notify_vendor = true; } diff --git a/tests/Feature/ExpenseApiTest.php b/tests/Feature/ExpenseApiTest.php index 8ffb2ab43d98..5cf695cb90d1 100644 --- a/tests/Feature/ExpenseApiTest.php +++ b/tests/Feature/ExpenseApiTest.php @@ -47,6 +47,44 @@ class ExpenseApiTest extends TestCase Model::reguard(); } + public function testExpensePutWithVendorStatus() + { + + + $data = + [ + 'vendor_id' => $this->vendor->hashed_id, + 'amount' => 10, + 'date' => '2021-10-01', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/expenses', $data); + + $arr = $response->json(); + $response->assertStatus(200); + + + $this->assertEquals($this->vendor->hashed_id, $arr['data']['vendor_id']); + + $data = [ + 'payment_date' => now()->format('Y-m-d') + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/expenses/'.$arr['data']['id'], $data); + + $arr = $response->json(); + $response->assertStatus(200); + + $this->assertEquals($this->vendor->hashed_id, $arr['data']['vendor_id']); + + } + public function testTransactionIdClearedOnDelete() { $bi = BankIntegration::factory()->create([ From f3dc80ae09f44a2bcc54ec81e57d7c99ff954273 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jul 2024 12:04:42 +1000 Subject: [PATCH 3/8] Roll back join queries --- app/Console/Commands/SendRemindersCron.php | 25 +++------- app/Jobs/Cron/RecurringInvoicesCron.php | 19 ++------ app/Jobs/Quote/QuoteCheckExpired.php | 47 ++++++------------- app/Jobs/Util/QuoteReminderJob.php | 47 ++++++------------- app/Services/Report/ARDetailReport.php | 9 +--- app/Services/Report/ProfitLoss.php | 9 +--- .../recurring_invoices/show.blade.php | 13 +---- .../ninja2020/subscriptions/show.blade.php | 4 +- 8 files changed, 49 insertions(+), 124 deletions(-) diff --git a/app/Console/Commands/SendRemindersCron.php b/app/Console/Commands/SendRemindersCron.php index 1c578c2c4aaa..7ce0ba0bdcdf 100644 --- a/app/Console/Commands/SendRemindersCron.php +++ b/app/Console/Commands/SendRemindersCron.php @@ -66,24 +66,13 @@ class SendRemindersCron extends Command ->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); - // }) + ->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()) { diff --git a/app/Jobs/Cron/RecurringInvoicesCron.php b/app/Jobs/Cron/RecurringInvoicesCron.php index 8c32e62b5c2f..b9c30656a5c8 100644 --- a/app/Jobs/Cron/RecurringInvoicesCron.php +++ b/app/Jobs/Cron/RecurringInvoicesCron.php @@ -54,21 +54,12 @@ class RecurringInvoicesCron ->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('client', function ($query) { + $query->where('is_deleted', 0) + ->where('deleted_at', null); }) - ->leftJoin('companies', function ($join) { - $join->on('recurring_invoices.company_id', '=', 'companies.id') - ->where('companies.is_disabled', 0); + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0); }) ->with('company') ->cursor(); diff --git a/app/Jobs/Quote/QuoteCheckExpired.php b/app/Jobs/Quote/QuoteCheckExpired.php index 9e6f278d359d..15a9ab9383de 100644 --- a/app/Jobs/Quote/QuoteCheckExpired.php +++ b/app/Jobs/Quote/QuoteCheckExpired.php @@ -53,23 +53,14 @@ class QuoteCheckExpired implements ShouldQueue ->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); - }) - + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0) + ->where('deleted_at', null); + }) + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0); + }) + ->whereBetween('quotes.due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) ->cursor() ->each(function ($quote) { @@ -84,22 +75,14 @@ class QuoteCheckExpired implements ShouldQueue ->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); + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0) + ->where('deleted_at', null); }) + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0); + }) + ->whereBetween('quotes.due_date', [now()->subDay()->startOfDay(), now()->startOfDay()->subSecond()]) ->cursor() ->each(function ($quote) { diff --git a/app/Jobs/Util/QuoteReminderJob.php b/app/Jobs/Util/QuoteReminderJob.php index 2df9da34f469..fdebf50198c7 100644 --- a/app/Jobs/Util/QuoteReminderJob.php +++ b/app/Jobs/Util/QuoteReminderJob.php @@ -65,22 +65,13 @@ class QuoteReminderJob implements ShouldQueue ->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); - }) + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0) + ->where('deleted_at', null); + }) + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0); + }) ->with('invitations')->chunk(50, function ($quotes) { foreach ($quotes as $quote) { $this->sendReminderForQuote($quote); @@ -101,22 +92,14 @@ class QuoteReminderJob implements ShouldQueue ->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); - }) + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0) + ->where('deleted_at', null); + }) + ->whereHas('company', function ($query) { + $query->where('is_disabled', 0); + }) + ->with('invitations')->chunk(50, function ($quotes) { foreach ($quotes as $quote) { diff --git a/app/Services/Report/ARDetailReport.php b/app/Services/Report/ARDetailReport.php index c27b0e4308c9..68d2dd11be68 100644 --- a/app/Services/Report/ARDetailReport.php +++ b/app/Services/Report/ARDetailReport.php @@ -92,13 +92,8 @@ class ARDetailReport extends BaseExport $query = Invoice::query() ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) ->withTrashed() - // ->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'); + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0); }) ->where('invoices.company_id', $this->company->id) ->where('invoices.is_deleted', 0) diff --git a/app/Services/Report/ProfitLoss.php b/app/Services/Report/ProfitLoss.php index c921df0f187e..09d392435a12 100644 --- a/app/Services/Report/ProfitLoss.php +++ b/app/Services/Report/ProfitLoss.php @@ -265,13 +265,8 @@ 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); - // }) - ->leftJoin('clients', function ($join) { - $join->on('payments.client_id', '=', 'clients.id') - ->where('clients.is_deleted', 0) - ->whereNull('clients.deleted_at'); + ->whereHas('client', function ($query) { + $query->where('is_deleted', 0); }) ->with(['company', 'client']) ->cursor() diff --git a/resources/views/portal/ninja2020/recurring_invoices/show.blade.php b/resources/views/portal/ninja2020/recurring_invoices/show.blade.php index df9a8c59bf9d..aed229b7fbe5 100644 --- a/resources/views/portal/ninja2020/recurring_invoices/show.blade.php +++ b/resources/views/portal/ninja2020/recurring_invoices/show.blade.php @@ -101,18 +101,7 @@ - - - - - - - - - - @if($invoice->subscription && $invoice->subscription?->allow_cancellation) - {{-- INV2-591 --}} - {{-- @if(false) --}} + @if($invoice->subscription && $invoice->subscription?->allow_cancellation && $invoice->status_id == 2)
diff --git a/resources/views/portal/ninja2020/subscriptions/show.blade.php b/resources/views/portal/ninja2020/subscriptions/show.blade.php index a2e226cd928c..c3540d56b788 100644 --- a/resources/views/portal/ninja2020/subscriptions/show.blade.php +++ b/resources/views/portal/ninja2020/subscriptions/show.blade.php @@ -73,7 +73,7 @@
@endif - @if($invoice->subscription && $invoice->subscription?->allow_cancellation) + @if($invoice->subscription && $invoice->subscription?->allow_cancellation && $invoice->status_id == 2)
@@ -92,7 +92,7 @@
@endif - @if($invoice->subscription && $invoice->subscription->allow_plan_changes) + @if($invoice->subscription && $invoice->subscription->allow_plan_changes && count($invoice->subscription->service()->getPlans()) > 0)

{{ ctrans('texts.change_plan') }}

{{ ctrans('texts.change_plan_description') }}

From 26bb71f067abb85c39231673082f48e6dfd06c61 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jul 2024 14:15:42 +1000 Subject: [PATCH 4/8] Adjustments for inclusive taxes --- app/Helpers/Invoice/InvoiceSumInclusive.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index cb297250b273..35464bd22ece 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -125,6 +125,7 @@ class InvoiceSumInclusive private function calculateInvoiceTaxes() { $amount = $this->total; + nlog("taxing this amount {$amount}"); if ($this->invoice->discount > 0 && $this->invoice->is_amount_discount) { $amount = $this->formatValue(($this->sub_total - $this->invoice->discount), 2); @@ -134,6 +135,8 @@ class InvoiceSumInclusive $amount = $this->formatValue(($this->sub_total - ($this->sub_total * ($this->invoice->discount / 100))), 2); } + $amount += $this->total_custom_values; + //Handles cases where the surcharge is not taxed // if(is_numeric($this->invoice->custom_surcharge1) && $this->invoice->custom_surcharge1 > 0 && !$this->invoice->custom_surcharge_tax1) { // $amount += $this->invoice->custom_surcharge1; From ec50e6f64bc1334cecb6f7a380e0a5012bc716fb Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 5 Jul 2024 14:37:21 +1000 Subject: [PATCH 5/8] Adjustments for inclusive taxes --- app/Helpers/Invoice/InvoiceSumInclusive.php | 44 ++++++++++----------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index 35464bd22ece..6df714231f04 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -74,8 +74,8 @@ class InvoiceSumInclusive { $this->calculateLineItems() ->calculateDiscount() - ->calculateCustomValues() //06-07-2024 - ->calculateInvoiceTaxes() //shuffle order of invoicetaxes/custom values to include the surcharge taxes in the tax map + ->calculateInvoiceTaxes() + ->calculateCustomValues() ->setTaxMap() ->calculateTotals() //just don't add the taxes!! ->calculateBalance() @@ -107,25 +107,26 @@ class InvoiceSumInclusive private function calculateCustomValues() { - $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge1, $this->invoice->custom_surcharge_tax1); + // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge1, $this->invoice->custom_surcharge_tax1); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge1); - $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge2, $this->invoice->custom_surcharge_tax2); + // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge2, $this->invoice->custom_surcharge_tax2); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge2); - $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge3, $this->invoice->custom_surcharge_tax3); + // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge3, $this->invoice->custom_surcharge_tax3); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge3); - $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge4, $this->invoice->custom_surcharge_tax4); + // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge4, $this->invoice->custom_surcharge_tax4); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge4); + $this->total += $this->total_custom_values; + return $this; } private function calculateInvoiceTaxes() { $amount = $this->total; - nlog("taxing this amount {$amount}"); if ($this->invoice->discount > 0 && $this->invoice->is_amount_discount) { $amount = $this->formatValue(($this->sub_total - $this->invoice->discount), 2); @@ -135,24 +136,22 @@ class InvoiceSumInclusive $amount = $this->formatValue(($this->sub_total - ($this->sub_total * ($this->invoice->discount / 100))), 2); } - $amount += $this->total_custom_values; - //Handles cases where the surcharge is not taxed - // if(is_numeric($this->invoice->custom_surcharge1) && $this->invoice->custom_surcharge1 > 0 && !$this->invoice->custom_surcharge_tax1) { - // $amount += $this->invoice->custom_surcharge1; - // } + if(is_numeric($this->invoice->custom_surcharge1) && $this->invoice->custom_surcharge1 > 0 && $this->invoice->custom_surcharge_tax1) { + $amount += $this->invoice->custom_surcharge1; + } - // if(is_numeric($this->invoice->custom_surcharge2) && $this->invoice->custom_surcharge2 > 0 && !$this->invoice->custom_surcharge_tax2) { - // $amount += $this->invoice->custom_surcharge2; - // } + if(is_numeric($this->invoice->custom_surcharge2) && $this->invoice->custom_surcharge2 > 0 && $this->invoice->custom_surcharge_tax2) { + $amount += $this->invoice->custom_surcharge2; + } - // if(is_numeric($this->invoice->custom_surcharge3) && $this->invoice->custom_surcharge3 > 0 && !$this->invoice->custom_surcharge_tax3) { - // $amount += $this->invoice->custom_surcharge3; - // } + if(is_numeric($this->invoice->custom_surcharge3) && $this->invoice->custom_surcharge3 > 0 && $this->invoice->custom_surcharge_tax3) { + $amount += $this->invoice->custom_surcharge3; + } - // if(is_numeric($this->invoice->custom_surcharge4) && $this->invoice->custom_surcharge4 > 0 && !$this->invoice->custom_surcharge_tax4) { - // $amount += $this->invoice->custom_surcharge4; - // } + if(is_numeric($this->invoice->custom_surcharge4) && $this->invoice->custom_surcharge4 > 0 && $this->invoice->custom_surcharge_tax4) { + $amount += $this->invoice->custom_surcharge4; + } if (is_string($this->invoice->tax_name1) && strlen($this->invoice->tax_name1) > 1) { $tax = $this->calcInclusiveLineTax($this->invoice->tax_rate1, $amount); @@ -173,8 +172,6 @@ class InvoiceSumInclusive $this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.floatval($this->invoice->tax_rate3).'%', 'total' => $tax]; } - $this->total += $this->total_custom_values; //06-07-2024 add the custom surcharge totals here after the tax calculations. - return $this; } @@ -398,5 +395,4 @@ class InvoiceSumInclusive { return $this; } - } From d55c77c59d898b76bd2804b2dd327b642a375675 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 6 Jul 2024 08:23:44 +1000 Subject: [PATCH 6/8] fixes for str_replace --- app/Utils/Traits/Pdf/PdfMaker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Utils/Traits/Pdf/PdfMaker.php b/app/Utils/Traits/Pdf/PdfMaker.php index 7d5259192b86..112570272f4a 100644 --- a/app/Utils/Traits/Pdf/PdfMaker.php +++ b/app/Utils/Traits/Pdf/PdfMaker.php @@ -39,7 +39,7 @@ trait PdfMaker $pdf->addChromiumArguments(config('ninja.snappdf_chromium_arguments')); } - $html = str_replace(['file:/', 'iframe', '<object', 'setHtml($html) From 8336cd3bf07c7783bd0030db1efd3396fac6a966 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 7 Jul 2024 07:30:50 +1000 Subject: [PATCH 7/8] Adjustments for quote partial due dates --- app/Http/Requests/Quote/StoreQuoteRequest.php | 4 ++-- app/Http/Requests/Quote/UpdateQuoteRequest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Http/Requests/Quote/StoreQuoteRequest.php b/app/Http/Requests/Quote/StoreQuoteRequest.php index e3d0bd4cfb52..4b2624ee7a6e 100644 --- a/app/Http/Requests/Quote/StoreQuoteRequest.php +++ b/app/Http/Requests/Quote/StoreQuoteRequest.php @@ -66,8 +66,8 @@ class StoreQuoteRequest extends Request $rules['exchange_rate'] = 'bail|sometimes|numeric'; $rules['line_items'] = 'array'; $rules['date'] = 'bail|sometimes|date:Y-m-d'; - $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date', 'after_or_equal:date']; - $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date']; + $rules['partial_due_date'] = ['bail', 'sometimes', 'nullable', 'exclude_if:partial,0', 'date', 'before:due_date', 'after_or_equal:date']; + $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date ?? '') > 1), 'date']; $rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999']; return $rules; diff --git a/app/Http/Requests/Quote/UpdateQuoteRequest.php b/app/Http/Requests/Quote/UpdateQuoteRequest.php index ce8c6eeeb273..77ac6f2f4abd 100644 --- a/app/Http/Requests/Quote/UpdateQuoteRequest.php +++ b/app/Http/Requests/Quote/UpdateQuoteRequest.php @@ -65,7 +65,7 @@ class UpdateQuoteRequest extends Request $rules['date'] = 'bail|sometimes|date:Y-m-d'; - $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date']; + $rules['partial_due_date'] = ['bail', 'sometimes', 'nullable', 'exclude_if:partial,0', 'date', 'before:due_date', 'after_or_equal:date']; $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', 'after_or_equal:date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date']; $rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999']; From d900398d182cd8ab32f39ec4c8b2c8f9b3c8fcca Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 7 Jul 2024 07:34:27 +1000 Subject: [PATCH 8/8] Adjustments for quote partial due dates --- app/Http/Requests/Invoice/StoreInvoiceRequest.php | 4 +++- app/Http/Requests/Invoice/UpdateInvoiceRequest.php | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php index 1b8d8693729e..767ac8db722d 100644 --- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php +++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php @@ -78,7 +78,9 @@ class StoreInvoiceRequest extends Request $rules['tax_name3'] = 'bail|sometimes|string|nullable'; $rules['exchange_rate'] = 'bail|sometimes|numeric'; $rules['partial'] = 'bail|sometimes|nullable|numeric|gte:0'; - $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date']; + $rules['partial_due_date'] = ['bail', 'sometimes', 'nullable', 'exclude_if:partial,0', 'date', 'before:due_date', 'after_or_equal:date']; + $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date ?? '') > 1), 'date']; + $rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999']; // $rules['amount'] = ['sometimes', 'bail', 'max:99999999999999']; diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 0c71d72ac8ed..9d960ef379c9 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -82,8 +82,8 @@ class UpdateInvoiceRequest extends Request $rules['date'] = 'bail|sometimes|date:Y-m-d'; - // $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date']; - // $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date']; + $rules['partial_due_date'] = ['bail', 'sometimes', 'nullable', 'exclude_if:partial,0', 'date', 'before:due_date', 'after_or_equal:date']; + $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', 'after_or_equal:date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date']; return $rules; }