diff --git a/VERSION.txt b/VERSION.txt index d1cf0f322798..9b4bab7a7e41 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.6 \ No newline at end of file +5.7.7 \ No newline at end of file diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index 89e4ba69f17d..3dac3bb6163f 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -549,7 +549,7 @@ class CheckData extends Command private function clientPaidToDateQuery() { - $results = \DB::select(\DB::raw(" + $results = \DB::select(" SELECT clients.id as client_id, clients.paid_to_date as client_paid_to_date, @@ -564,14 +564,14 @@ class CheckData extends Command GROUP BY clients.id HAVING payments_applied != client_paid_to_date ORDER BY clients.id; - ")->getValue(DB::connection()->getQueryGrammar())); + "); return $results; } private function clientCreditPaymentables($client) { - $results = \DB::select(\DB::raw(" + $results = \DB::select(" SELECT SUM(paymentables.amount - paymentables.refunded) as credit_payment FROM payments @@ -583,7 +583,7 @@ class CheckData extends Command AND paymentables.amount > 0 AND payments.is_deleted = 0 AND payments.client_id = ?; - ")->getValue(DB::connection()->getQueryGrammar()), [App\Models\Credit::class, $client->id]); + ", [App\Models\Credit::class, $client->id]); return $results; } @@ -619,110 +619,11 @@ class CheckData extends Command } $this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect paid to dates"); - } - - private function checkPaidToDates() - { - $this->wrong_paid_to_dates = 0; - $credit_total_applied = 0; - - $clients = DB::table('clients') - ->leftJoin('payments', function ($join) { - $join->on('payments.client_id', '=', 'clients.id') - ->where('payments.is_deleted', 0) - ->whereIn('payments.status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]); - }) - ->where('clients.is_deleted', 0) - ->where('clients.updated_at', '>', now()->subDays(2)) - ->groupBy('clients.id') - ->havingRaw('clients.paid_to_date != sum(coalesce(payments.amount - payments.refunded, 0))') - ->get(['clients.id', 'clients.paid_to_date', DB::raw('sum(coalesce(payments.amount - payments.refunded, 0)) as amount')->getValue(DB::connection()->getQueryGrammar())]); - - /* Due to accounting differences we need to perform a second loop here to ensure there actually is an issue */ - $clients->each(function ($client_record) use ($credit_total_applied) { - $client = Client::withTrashed()->find($client_record->id); - - $total_invoice_payments = 0; - - foreach ($client->invoices()->where('is_deleted', false)->where('status_id', '>', 1)->get() as $invoice) { - $total_invoice_payments += $invoice->payments() - ->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]) - ->selectRaw('sum(paymentables.amount - paymentables.refunded) as p') - ->pluck('p') - ->first(); - } - - //commented IN 27/06/2021 - sums ALL client payments AND the unapplied amounts to match the client paid to date - $p = Payment::where('client_id', $client->id) - ->where('is_deleted', 0) - ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]) - // ->sum(DB::Raw('amount - applied')->getValue(DB::connection()->getQueryGrammar())); - ->selectRaw('SUM(payments.amount - payments.applied) as amount')->first()->amount ?? 0; - $total_invoice_payments += $p; - - // 10/02/21 - foreach ($client->payments as $payment) { - $credit_total_applied += $payment->paymentables() - ->where('paymentable_type', App\Models\Credit::class) - ->selectRaw('sum(paymentables.amount - paymentables.refunded) as p') - ->pluck('p') - ->first(); - } - - if ($credit_total_applied < 0) { - $total_invoice_payments += $credit_total_applied; - } - - if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) { - $this->wrong_paid_to_dates++; - - $this->logMessage($client->present()->name().' id = # '.$client->id." - Paid to date does not match Client Paid To Date = {$client->paid_to_date} - Invoice Payments = {$total_invoice_payments}"); - - $this->isValid = false; - - if ($this->option('paid_to_date')) { - $this->logMessage("# {$client->id} " . $client->present()->name().' - '.$client->number." Fixing {$client->paid_to_date} to {$total_invoice_payments}"); - $client->paid_to_date = $total_invoice_payments; - $client->save(); - } - } - }); - - $this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect paid to dates"); - } - - private function checkInvoicePayments() - { - $this->wrong_balances = 0; - - Client::query()->cursor()->where('is_deleted', 0)->where('clients.updated_at', '>', now()->subDays(2))->each(function ($client) { - $client->invoices->where('is_deleted', false)->whereIn('status_id', '!=', Invoice::STATUS_DRAFT)->each(function ($invoice) use ($client) { - $total_paid = $invoice->payments() - ->where('is_deleted', false)->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]) - ->selectRaw('sum(paymentables.amount - paymentables.refunded) as p') - ->pluck('p') - ->first(); - - $total_credit = $invoice->credits()->get()->sum('amount'); - - $calculated_paid_amount = $invoice->amount - $invoice->balance - $total_credit; - - if ((string)$total_paid != (string)($invoice->amount - $invoice->balance - $total_credit)) { - $this->wrong_balances++; - - $this->logMessage($client->present()->name().' - '.$client->id." - Total Paid = {$total_paid} != Calculated Total = {$calculated_paid_amount}"); - - $this->isValid = false; - } - }); - }); - - $this->logMessage("{$this->wrong_balances} clients with incorrect invoice balances"); - } + } private function clientBalanceQuery() { - $results = \DB::select(\DB::raw(" + $results = \DB::select(" SELECT SUM(invoices.balance) as invoice_balance, clients.id as client_id, @@ -736,7 +637,7 @@ class CheckData extends Command GROUP BY clients.id HAVING invoice_balance != clients.balance ORDER BY clients.id; - ")->getValue(DB::connection()->getQueryGrammar())); + "); return $results; } @@ -813,7 +714,7 @@ class CheckData extends Command private function invoiceBalanceQuery() { - $results = \DB::select(\DB::raw(" + $results = \DB::select(" SELECT clients.id, clients.balance, @@ -827,7 +728,7 @@ class CheckData extends Command GROUP BY clients.id HAVING(invoices_balance != clients.balance) ORDER BY clients.id; - ")->getValue(DB::connection()->getQueryGrammar())); + "); return $results; } @@ -961,7 +862,7 @@ class CheckData extends Command } $records = DB::table($table) ->join($tableName, "{$tableName}.id", '=', "{$table}.{$field}_id") - ->where("{$table}.{$company_id}", '!=', DB::raw("{$tableName}.company_id")->getValue(DB::connection()->getQueryGrammar())) + ->where("{$table}.{$company_id}", '!=', "{$tableName}.company_id") ->get(["{$table}.id"]); if ($records->count()) { @@ -971,11 +872,6 @@ class CheckData extends Command } } - // foreach(User::cursor() as $user) { - - // $records = Company::where('account_id',) - - // } } public function pluralizeEntityType($type) diff --git a/app/Http/Controllers/SchedulerController.php b/app/Http/Controllers/SchedulerController.php index 91f64068d427..6ec669972dde 100644 --- a/app/Http/Controllers/SchedulerController.php +++ b/app/Http/Controllers/SchedulerController.php @@ -15,7 +15,10 @@ class SchedulerController extends Controller { public function index() { - if (auth()->user()->company()->account->latest_version == '0.0.0') { + /** @var \App\Models\User $user */ + $user = auth()->user(); + + if ($user->company()->account->latest_version == '0.0.0') { return response()->json(['message' => ctrans('texts.scheduler_has_never_run')], 400); } else { return response()->json(['message' => ctrans('texts.scheduler_has_run')], 200); diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php new file mode 100644 index 000000000000..ca694e6103ab --- /dev/null +++ b/app/Http/Controllers/SearchController.php @@ -0,0 +1,190 @@ +user(); + + return response()->json([ + 'clients' => $this->clientMap($user), + 'client_contacts' => $this->clientContactMap($user), + 'invoices' => $this->invoiceMap($user), + 'settings' => $this->settingsMap(), + ], 200); + + } + + private function clientMap(User $user) { + + return Client::query() + ->company() + ->when($user->cannot('view_all') || $user->cannot('view_client'), function ($query) use($user) { + $query->where('user_id', $user->id); + }) + ->cursor() + ->map(function ($client){ + return [ + 'name' => $client->present()->name(), + 'type' => '/client', + 'id' => $client->hashed_id, + 'path' => "/clients/{$client->hashed_id}/edit" + ]; + }); + } + + private function clientContactMap(User $user) { + + return ClientContact::query() + ->company() + ->with('client') + ->when($user->cannot('view_all') || $user->cannot('view_client'), function ($query) use($user) { + $query->where('user_id', $user->id); + }) + ->cursor() + ->map(function ($contact){ + return [ + 'name' => $contact->present()->search_display(), + 'type' => '/client_contact', + 'id' => $contact->client->hashed_id, + 'path' => "/clients/{$contact->client->hashed_id}" + ]; + }); + } + + private function invoiceMap(User $user) { + + return Invoice::query() + ->company() + ->with('client') + ->when($user->cannot('view_all') || $user->cannot('view_invoice'), function ($query) use($user) { + $query->where('user_id', $user->id); + }) + ->cursor() + ->map(function ($invoice){ + return [ + 'name' => $invoice->client->present()->name() . ' - ' . $invoice->number, + 'type' => '/invoice', + 'id' => $invoice->hashed_id, + 'path' => "/clients/{$invoice->hashed_id}/edit" + ]; + }); + } + + private function settingsMap() { + + $paths = [ + 'user_details' => '/settings/user_details', + 'password' => '/settings/user_details/password', + 'connect' => '/settings/user_details/connect', + 'accent_color' => '/settings/user_details/accent_color', + 'notifications' => '/settings/user_details/notifications', + 'enable_two_factor' => '/settings/user_details/enable_two_factor', + 'custom_fields' => '/settings/user_details/custom_fields', + 'preferences' => '/settings/user_details/preferences', + 'company_details' => '/settings/company_details', + 'company_details,details' => '/settings/company_details/details', + 'company_details,address' => '/settings/company_details/address', + 'company_details,logo' => '/settings/company_details/logo', + 'company_details,defaults' => '/settings/company_details/defaults', + 'company_details,documents' => '/settings/company_details/documents', + 'company_details,custom_fields' => '/settings/company_details/custom_fields', + 'localization' => '/settings/localization', + 'localization,custom_labels' => '/settings/localization/custom_labels', + 'online_payments' => '/settings/online_payments', + 'tax_settings' => '/settings/tax_settings', + 'product_settings' => '/settings/product_settings', + 'task_settings' => '/settings/task_settings', + 'expense_settings' => '/settings/expense_settings', + 'workflow_settings' => '/settings/workflow_settings', + 'import_export' => '/settings/import_export', + 'account_management' => '/settings/account_management', + 'account_management,overview' => '/settings/account_management/overview', + 'account_management,enabled_modules' => '/settings/account_management/enabled_modules', + 'account_management,integrations' => '/settings/account_management/integrations', + 'account_management,security_settings' => '/settings/account_management/security_settings', + 'account_management,danger_zone' => '/settings/account_management/danger_zone', + 'backup_restore' => '/settings/backup_restore', + 'backup_restore,restore' => '/settings/backup_restore/restore', + 'backup_restore,backup' => '/settings/backup_restore/backup', + 'custom_fields' => '/settings/custom_fields', + 'custom_fields,company' => '/settings/custom_fields/company', + 'custom_fields,clients' => '/settings/custom_fields/clients', + 'custom_fields,products' => '/settings/custom_fields/products', + 'custom_fields,invoices' => '/settings/custom_fields/invoices', + 'custom_fields,payments' => '/settings/custom_fields/payments', + 'custom_fields,projects' => '/settings/custom_fields/projects', + 'custom_fields,tasks' => '/settings/custom_fields/tasks', + 'custom_fields,vendors' => '/settings/custom_fields/vendors', + 'custom_fields,expenses' => '/settings/custom_fields/expenses', + 'custom_fields,users' => '/settings/custom_fields/users', + 'custom_fields,quotes' => '/settings/custom_fields/quotes', + 'custom_fields,credits' => '/settings/custom_fields/credits', + 'generated_numbers' => '/settings/generated_numbers', + 'client_portal' => '/settings/client_portal', + 'email_settings' => '/settings/email_settings', + 'templates_and_reminders' => '/settings/templates_and_reminders', + 'bank_accounts' => '/settings/bank_accounts', + 'group_settings' => '/settings/group_settings', + 'subscriptions' => '/settings/subscriptions', + 'schedules' => '/settings/schedules', + 'users' => '/settings/users', + 'system_logs' => '/settings/system_logs', + 'payment_terms' => '/settings/payment_terms', + 'tax_rates' => '/settings/tax_rates', + 'task_statuses' => '/settings/task_statuses', + 'expense_categories' => '/settings/expense_categories', + 'integrations' => '/settings/integrations', + 'integrations,api_tokens' => '/settings/integrations/api_tokens', + 'integrations,api_webhooks' => '/settings/integrations/api_webhooks', + 'integrations,analytics' => '/settings/integrations/analytics', + 'gateways' => '/settings/gateways', + 'gateways,create' => '/settings/gateways/create', + 'bank_accounts,transaction_rules' => '/settings/bank_accounts/transaction_rules', + 'bank_accounts,transaction_rules/create' => '/settings/bank_accounts/transaction_rules/create', + ]; + + $data = []; + + foreach($paths as $key => $value) { + + $translation = ''; + + foreach(explode(",", $key) as $transkey) { + $translation .= ctrans("texts.{$transkey}")." "; + } + + $translation = rtrim($translation, " "); + + $data[] = [ + 'id' => $translation, + 'path' => $value, + 'type' => $transkey, + 'name' => $translation, + ]; + } + + ksort($data); + + return $data; + } + +} diff --git a/app/Http/Requests/Client/BulkClientRequest.php b/app/Http/Requests/Client/BulkClientRequest.php index b77c09a5277d..c18ac8fa3d10 100644 --- a/app/Http/Requests/Client/BulkClientRequest.php +++ b/app/Http/Requests/Client/BulkClientRequest.php @@ -31,8 +31,11 @@ class BulkClientRequest extends Request public function rules() { + /** @var \App\Models\User $user */ + $user = auth()->user(); + return [ - 'ids' => ['required','bail','array',Rule::exists('clients', 'id')->where('company_id', auth()->user()->company()->id)], + 'ids' => ['required','bail','array',Rule::exists('clients', 'id')->where('company_id', $user->company()->id)], 'action' => 'in:archive,restore,delete' ]; } diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index def035b0c98d..2fb9a589e082 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -20,7 +20,7 @@ class Request extends FormRequest use MakesHash; use RuntimeFormRequest; - protected $file_validation = 'sometimes|file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx,webp,xml,zip|max:100000'; + protected $file_validation = 'sometimes|file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx,webp,xml,zip,csv|max:100000'; /** * Get the validation rules that apply to the request. * diff --git a/app/Http/Requests/Search/GenericSearchRequest.php b/app/Http/Requests/Search/GenericSearchRequest.php new file mode 100644 index 000000000000..8bd4f4b46970 --- /dev/null +++ b/app/Http/Requests/Search/GenericSearchRequest.php @@ -0,0 +1,43 @@ + 'bail|sometimes|string' + ]; + + return $rules; + } + + public function prepareForValidation() + { + $input = $this->all(); + + $this->replace($input); + } +} diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index 2568213db695..e401e85aa058 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -746,12 +746,7 @@ class BaseImport if($user) return $user->id; - $user = User::where('account_id', $this->company->account->id) - ->where( - \DB::raw('CONCAT_WS(" ", first_name, last_name)')->getValue(\DB::connection()->getQueryGrammar()), - 'like', - '%'.$user_hash.'%' - ) + $user = User::whereRaw("account_id = ? AND CONCAT_WS(' ', first_name, last_name) like ?", [$this->company->account_id, '%'.$user_hash.'%']) ->first(); if ($user) { diff --git a/app/Jobs/Ninja/CheckCompanyData.php b/app/Jobs/Ninja/CheckCompanyData.php index 3c9818beffec..9899bdff7746 100644 --- a/app/Jobs/Ninja/CheckCompanyData.php +++ b/app/Jobs/Ninja/CheckCompanyData.php @@ -248,19 +248,6 @@ class CheckCompanyData implements ShouldQueue $this->is_valid = false; } - // if ($this->option('fix') == 'true') { - // foreach ($clients as $client) { - // $contact = new ClientContact(); - // $contact->company_id = $client->company_id; - // $contact->user_id = $client->user_id; - // $contact->client_id = $client->id; - // $contact->is_primary = true; - // $contact->send_invoice = true; - // $contact->contact_key = str_random(config('ninja.key_length')); - // $contact->save(); - // } - // } - // check for more than one primary contact $clients = DB::table('clients') ->where('clients.company_id', $this->company->id) @@ -272,11 +259,7 @@ class CheckCompanyData implements ShouldQueue ->groupBy('clients.id') ->havingRaw('count(client_contacts.id) != 1'); - // if ($this->option('client_id')) { - // $clients->where('clients.id', '=', $this->option('client_id')); - // } - - $clients = $clients->get(['clients.id', DB::raw('count(client_contacts.id)')->getValue(DB::connection()->getQueryGrammar())]); + $clients = $clients->get(['clients.id', DB::raw('count(client_contacts.id)')]); $this->company_data[] = $clients->count().' clients without a single primary contact'; if ($clients->count() > 0) { @@ -315,7 +298,7 @@ class CheckCompanyData implements ShouldQueue } $records = DB::table($table) ->join($tableName, "{$tableName}.id", '=', "{$table}.{$field}_id") - ->where("{$table}.{$company_id}", '!=', DB::raw("{$tableName}.company_id")->getValue(DB::connection()->getQueryGrammar())) + ->where("{$table}.{$company_id}", '!=', "{$tableName}.company_id") ->get(["{$table}.id"]); if ($records->count()) { diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index 133ddce26394..bfb09f42abec 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -302,7 +302,7 @@ class Import implements ShouldQueue // 10/02/21 foreach ($client->payments as $payment) { - $credit_total_applied += $payment->paymentables()->where('paymentable_type', \App\Models\Credit::class)->get()->sum(\DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + $credit_total_applied += $payment->paymentables()->where('paymentable_type', \App\Models\Credit::class)->get()->sum('amount'); } if ($credit_total_applied < 0) { diff --git a/app/Models/Presenters/ClientContactPresenter.php b/app/Models/Presenters/ClientContactPresenter.php index dc2229d8e2c9..177421a6edfa 100644 --- a/app/Models/Presenters/ClientContactPresenter.php +++ b/app/Models/Presenters/ClientContactPresenter.php @@ -32,11 +32,16 @@ class ClientContactPresenter extends EntityPresenter public function first_name() { - return $this->entity->first_name ?: ''; + return $this->entity->first_name ?? ''; } public function last_name() { - return $this->entity->last_name ?: ''; + return $this->entity->last_name ?? ''; + } + + public function search_display() + { + return $this->name().' <'.$this->entity->email.'>' ?? ''; } } diff --git a/app/Services/Chart/ChartQueries.php b/app/Services/Chart/ChartQueries.php index 6aee8c1a4230..da83406a46aa 100644 --- a/app/Services/Chart/ChartQueries.php +++ b/app/Services/Chart/ChartQueries.php @@ -25,7 +25,7 @@ trait ChartQueries { $user_filter = $this->is_admin ? '' : 'AND expenses.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(expenses.amount) as amount, IFNULL(expenses.currency_id, :company_currency) as currency_id FROM expenses @@ -34,7 +34,7 @@ trait ChartQueries AND (expenses.date BETWEEN :start_date AND :end_date) {$user_filter} GROUP BY currency_id - ")->getValue(DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getExpenseChartQuery($start_date, $end_date, $currency_id) @@ -42,7 +42,7 @@ trait ChartQueries $user_filter = $this->is_admin ? '' : 'AND expenses.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(expenses.amount) as total, expenses.date, @@ -54,7 +54,7 @@ trait ChartQueries {$user_filter} GROUP BY expenses.date HAVING currency_id = :currency_id - ")->getValue(DB::connection()->getQueryGrammar()), [ + ", [ 'company_currency' => $this->company->settings->currency_id, 'currency_id' => $currency_id, 'company_id' => $this->company->id, @@ -71,7 +71,7 @@ trait ChartQueries $user_filter = $this->is_admin ? '' : 'AND payments.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(payments.amount) as amount, IFNULL(payments.currency_id, :company_currency) as currency_id FROM payments @@ -80,7 +80,7 @@ trait ChartQueries AND payments.company_id = :company_id AND (payments.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ")->getValue(DB::connection()->getQueryGrammar()), [ + ", [ 'company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, @@ -93,7 +93,7 @@ trait ChartQueries $user_filter = $this->is_admin ? '' : 'AND payments.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(payments.amount - payments.refunded) as total, payments.date, @@ -106,7 +106,7 @@ trait ChartQueries AND (payments.date BETWEEN :start_date AND :end_date) GROUP BY payments.date HAVING currency_id = :currency_id - ")->getValue(DB::connection()->getQueryGrammar()), [ + ", [ 'company_currency' => $this->company->settings->currency_id, 'currency_id' => $currency_id, 'company_id' => $this->company->id, @@ -123,7 +123,7 @@ trait ChartQueries $user_filter = $this->is_admin ? '' : 'AND clients.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.balance) as amount, COUNT(*) as outstanding_count, @@ -139,14 +139,14 @@ trait ChartQueries AND invoices.balance > 0 AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ")->getValue(DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getRevenueQueryX($start_date, $end_date) { $user_filter = $this->is_admin ? '' : 'AND clients.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.paid_to_date) as paid_to_date, IFNULL(CAST(JSON_UNQUOTE(JSON_EXTRACT( clients.settings, '$.currency_id' )) AS SIGNED), :company_currency) AS currency_id @@ -161,14 +161,14 @@ trait ChartQueries AND invoices.status_id IN (3,4) AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ")->getValue(DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getRevenueQuery($start_date, $end_date) { $user_filter = $this->is_admin ? '' : 'AND payments.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(payments.amount - payments.refunded) as paid_to_date, payments.currency_id AS currency_id @@ -179,14 +179,14 @@ trait ChartQueries AND payments.status_id IN (1,4,5,6) AND (payments.date BETWEEN :start_date AND :end_date) GROUP BY payments.currency_id - ")->getValue(DB::connection()->getQueryGrammar()), ['company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ", ['company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getInvoicesQuery($start_date, $end_date) { $user_filter = $this->is_admin ? '' : 'AND clients.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.amount) as invoiced_amount, IFNULL(CAST(JSON_UNQUOTE(JSON_EXTRACT( clients.settings, '$.currency_id' )) AS SIGNED), :company_currency) AS currency_id @@ -201,14 +201,14 @@ trait ChartQueries AND invoices.is_deleted = 0 AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ")->getValue(DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getOutstandingChartQuery($start_date, $end_date, $currency_id) { $user_filter = $this->is_admin ? '' : 'AND clients.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.balance) as total, invoices.date, @@ -224,7 +224,7 @@ trait ChartQueries AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY invoices.date HAVING currency_id = :currency_id - ")->getValue(DB::connection()->getQueryGrammar()), [ + ", [ 'company_currency' => (int) $this->company->settings->currency_id, 'currency_id' => $currency_id, 'company_id' => $this->company->id, @@ -238,7 +238,7 @@ trait ChartQueries { $user_filter = $this->is_admin ? '' : 'AND clients.user_id = '.$this->user->id; - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.amount) as total, invoices.date, @@ -254,7 +254,7 @@ trait ChartQueries AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY invoices.date HAVING currency_id = :currency_id - ")->getValue(DB::connection()->getQueryGrammar()), [ + ", [ 'company_currency' => (int) $this->company->settings->currency_id, 'currency_id' => $currency_id, 'company_id' => $this->company->id, diff --git a/app/Services/Chart/ChartQueriesLegacy.php b/app/Services/Chart/ChartQueriesLegacy.php index f79bc06d938f..1091defff5e6 100644 --- a/app/Services/Chart/ChartQueriesLegacy.php +++ b/app/Services/Chart/ChartQueriesLegacy.php @@ -24,7 +24,7 @@ trait ChartQueriesLegacy public function getExpenseQuery($start_date, $end_date) { - return DB::select(DB::raw(' + return DB::select(' SELECT sum(expenses.amount) as amount, IFNULL(expenses.currency_id, :company_currency) as currency_id FROM expenses @@ -32,12 +32,12 @@ trait ChartQueriesLegacy AND expenses.company_id = :company_id AND (expenses.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ')->getValue(DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ', ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getExpenseChartQuery($start_date, $end_date, $currency_id) { - return DB::select(DB::raw(' + return DB::select(' SELECT sum(expenses.amount) as total, expenses.date, @@ -48,7 +48,7 @@ trait ChartQueriesLegacy AND expenses.is_deleted = 0 GROUP BY expenses.date HAVING currency_id = :currency_id - ')->getValue(DB::connection()->getQueryGrammar()), [ + ', [ 'company_currency' => $this->company->settings->currency_id, 'currency_id' => $currency_id, 'company_id' => $this->company->id, @@ -62,7 +62,7 @@ trait ChartQueriesLegacy */ public function getPaymentQuery($start_date, $end_date) { - return DB::select(DB::raw(' + return DB::select(' SELECT sum(payments.amount) as amount, IFNULL(payments.currency_id, :company_currency) as currency_id FROM payments @@ -70,7 +70,7 @@ trait ChartQueriesLegacy AND payments.company_id = :company_id AND (payments.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ')->getValue(DB::connection()->getQueryGrammar()), [ + ', [ 'company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, @@ -80,7 +80,7 @@ trait ChartQueriesLegacy public function getPaymentChartQuery($start_date, $end_date, $currency_id) { - return DB::select(DB::raw(' + return DB::select(' SELECT sum(payments.amount - payments.refunded) as total, payments.date, @@ -92,7 +92,7 @@ trait ChartQueriesLegacy AND payments.is_deleted = 0 GROUP BY payments.date HAVING currency_id = :currency_id - ')->getValue(DB::connection()->getQueryGrammar()), [ + ', [ 'company_currency' => $this->company->settings->currency_id, 'currency_id' => $currency_id, 'company_id' => $this->company->id, @@ -106,7 +106,7 @@ trait ChartQueriesLegacy */ public function getOutstandingQuery($start_date, $end_date) { - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.balance) as amount, IFNULL(JSON_EXTRACT( settings, '$.currency_id' ), :company_currency) AS currency_id @@ -120,12 +120,12 @@ trait ChartQueriesLegacy AND invoices.is_deleted = 0 AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ")->getValue(DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getRevenueQuery($start_date, $end_date) { - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.paid_to_date) as paid_to_date, IFNULL(JSON_EXTRACT( settings, '$.currency_id' ), :company_currency) AS currency_id @@ -139,12 +139,12 @@ trait ChartQueriesLegacy AND invoices.is_deleted = 0 AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - "), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); + ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); } public function getInvoiceChartQuery($start_date, $end_date, $currency_id) { - return DB::select(DB::raw(" + return DB::select(" SELECT sum(invoices.amount) as total, invoices.date, @@ -159,7 +159,7 @@ trait ChartQueriesLegacy AND invoices.is_deleted = 0 GROUP BY invoices.date HAVING currency_id = :currency_id - ")->getValue(DB::connection()->getQueryGrammar()), [ + ", [ 'company_currency' => (int) $this->company->settings->currency_id, 'currency_id' => $currency_id, 'company_id' => $this->company->id, diff --git a/app/Services/Chart/ChartServiceLegacy.php b/app/Services/Chart/ChartServiceLegacy.php index 84e53cec935c..372d89ddb919 100644 --- a/app/Services/Chart/ChartServiceLegacy.php +++ b/app/Services/Chart/ChartServiceLegacy.php @@ -15,6 +15,7 @@ use App\Models\Client; use App\Models\Company; use App\Models\Expense; use Illuminate\Support\Facades\Cache; +use App\Services\Chart\ChartQueriesLegacy; class ChartServiceLegacy { diff --git a/app/Services/Client/ClientService.php b/app/Services/Client/ClientService.php index 25b5a827aaef..96878cd2480e 100644 --- a/app/Services/Client/ClientService.php +++ b/app/Services/Client/ClientService.php @@ -82,7 +82,6 @@ class ClientService ->where('is_deleted', 0) ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]) ->selectRaw('SUM(payments.amount - payments.applied) as amount')->first()->amount ?? 0; - // ->sum(DB::Raw('amount - applied')->getValue(DB::connection()->getQueryGrammar())); DB::connection(config('database.default'))->transaction(function () use ($amount) { $this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first(); diff --git a/app/Services/Invoice/HandleRestore.php b/app/Services/Invoice/HandleRestore.php index d2a4eeb1e1cc..836e604f0b75 100644 --- a/app/Services/Invoice/HandleRestore.php +++ b/app/Services/Invoice/HandleRestore.php @@ -96,17 +96,17 @@ class HandleRestore extends AbstractService $this->adjustment_amount += $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); $this->adjustment_amount += $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('refunded')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); //14/07/2023 - do not include credits in the payment amount $this->adjustment_amount -= $payment->paymentables ->where('paymentable_type', '=', 'App\Models\Credit') - ->sum(DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); } @@ -129,16 +129,16 @@ class HandleRestore extends AbstractService $payment_adjustment = $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); $payment_adjustment -= $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('refunded')->getValue(DB::connection()->getQueryGrammar())); + ->sum('refunded'); $payment_adjustment -= $payment->paymentables ->where('paymentable_type', '=', 'App\Models\Credit') - ->sum(DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); $payment->amount += $payment_adjustment; $payment->applied += $payment_adjustment; diff --git a/app/Services/Invoice/MarkInvoiceDeleted.php b/app/Services/Invoice/MarkInvoiceDeleted.php index d2f1aef2bed7..8402bda4f965 100644 --- a/app/Services/Invoice/MarkInvoiceDeleted.php +++ b/app/Services/Invoice/MarkInvoiceDeleted.php @@ -88,17 +88,17 @@ class MarkInvoiceDeleted extends AbstractService $payment_adjustment = $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); $payment_adjustment -= $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('refunded')->getValue(DB::connection()->getQueryGrammar())); + ->sum('refunded'); //14-07-2023 - Do not include credits in the payment adjustment. $payment_adjustment -= $payment->paymentables ->where('paymentable_type', '=', 'App\Models\Credit') - ->sum(DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); $payment->amount -= $payment_adjustment; $payment->applied -= $payment_adjustment; @@ -121,12 +121,12 @@ class MarkInvoiceDeleted extends AbstractService $this->adjustment_amount += $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('amount')->getValue(DB::connection()->getQueryGrammar())); + ->sum('amount'); $this->adjustment_amount -= $payment->paymentables ->where('paymentable_type', '=', 'invoices') ->where('paymentable_id', $this->invoice->id) - ->sum(DB::raw('refunded')->getValue(DB::connection()->getQueryGrammar())); + ->sum('refunded'); } $this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded'); diff --git a/app/Services/Report/ProfitLoss.php b/app/Services/Report/ProfitLoss.php index 4cd499bb38ac..00f0c773df79 100644 --- a/app/Services/Report/ProfitLoss.php +++ b/app/Services/Report/ProfitLoss.php @@ -178,17 +178,6 @@ class ProfitLoss $this->credit_taxes += $map->tax_amount_credit_converted; } - // $invoices = $this->invoicePaymentIncome(); - - // $this->income = 0; - // $this->income_taxes = 0; - // $this->income_map = $invoices; - - // foreach($invoices as $invoice){ - // $this->income += $invoice->net_converted_amount; - // $this->income_taxes += $invoice->net_converted_taxes; - // } - return $this; } @@ -232,7 +221,7 @@ class ProfitLoss */ private function invoiceIncome() { - return \DB::select(\DB::raw(" + return \DB::select(" SELECT sum(invoices.amount) as amount, sum(invoices.total_taxes) as total_taxes, @@ -250,7 +239,7 @@ class ProfitLoss AND invoices.is_deleted = 0 AND (invoices.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ")->getValue(\DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); + ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); } /** @@ -402,28 +391,6 @@ class ProfitLoss return $csv->toString(); } - private function invoicePaymentIncome() - { - return \DB::select(\DB::raw(" - SELECT - sum(invoices.amount - invoices.balance) as amount, - sum(invoices.total_taxes) * ((sum(invoices.amount - invoices.balance)/invoices.amount)) as total_taxes, - (sum(invoices.amount - invoices.balance) / IFNULL(invoices.exchange_rate, 1)) AS net_converted_amount, - (sum(invoices.total_taxes) * ((sum(invoices.amount - invoices.balance)/invoices.amount)) / IFNULL(invoices.exchange_rate, 1)) AS net_converted_taxes, - IFNULL(JSON_EXTRACT( settings, '$.currency_id' ), :company_currency) AS currency_id - FROM clients - JOIN invoices - on invoices.client_id = clients.id - WHERE invoices.status_id IN (3,4) - AND invoices.company_id = :company_id - AND invoices.amount > 0 - AND clients.is_deleted = 0 - AND invoices.is_deleted = 0 - AND (invoices.date BETWEEN :start_date AND :end_date) - GROUP BY currency_id - ")->getValue(\DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); - } - /** +"payments": "12260.870000", +"payments_converted": "12260.870000000000", @@ -431,7 +398,7 @@ class ProfitLoss */ private function paymentIncome() { - return \DB::select(\DB::raw(' + return \DB::select(' SELECT SUM(coalesce(payments.amount - payments.refunded,0)) as payments, SUM(coalesce(payments.amount - payments.refunded,0)) * IFNULL(payments.exchange_rate ,1) as payments_converted, @@ -447,7 +414,7 @@ class ProfitLoss AND (payments.date BETWEEN :start_date AND :end_date) GROUP BY currency_id ORDER BY currency_id; - ')->getValue(\DB::connection()->getQueryGrammar()), ['company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); + ', ['company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); } private function expenseData() @@ -545,7 +512,7 @@ class ProfitLoss private function expenseCalcWithTax() { - return \DB::select(\DB::raw(' + return \DB::select(' SELECT sum(expenses.amount) as amount, IFNULL(expenses.currency_id, :company_currency) as currency_id FROM expenses @@ -553,7 +520,7 @@ class ProfitLoss AND expenses.company_id = :company_id AND (expenses.date BETWEEN :start_date AND :end_date) GROUP BY currency_id - ')->getValue(\DB::connection()->getQueryGrammar()), ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); + ', ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); } private function setBillingReportType() diff --git a/app/Services/Report/TaxSummaryReport.php b/app/Services/Report/TaxSummaryReport.php index 5cbb8de0c30b..661f741865cf 100644 --- a/app/Services/Report/TaxSummaryReport.php +++ b/app/Services/Report/TaxSummaryReport.php @@ -75,8 +75,6 @@ class TaxSummaryReport extends BaseExport $this->input['report_keys'] = $this->report_keys; } - $this->csv->insertOne($this->buildHeader()); - $query = Invoice::query() ->withTrashed() ->whereIn('status_id', [2,3,4]) @@ -109,18 +107,18 @@ class TaxSummaryReport extends BaseExport $accrual_map[$key]['tax_amount'] += $tax['total']; //cash + $key = $tax['name']; + + if(!isset($cash_map[$key])) { + $cash_map[$key]['tax_amount'] = 0; + } + if(in_array($invoice->status_id, [Invoice::STATUS_PARTIAL,Invoice::STATUS_PAID])){ - $key = $tax['name']; - - if(!isset($cash_map[$key])) { - $cash_map[$key]['tax_amount'] = 0; - } - - if($invoice->status_id == Invoice::STATUS_PAID) - $cash_map[$key]['tax_amount'] += $tax['total']; - else - $cash_map[$key]['tax_amount'] += (($invoice->amount - $invoice->balance) / $invoice->balance) * $tax['total'] ?? 0; + if($invoice->status_id == Invoice::STATUS_PAID) + $cash_map[$key]['tax_amount'] += $tax['total']; + else + $cash_map[$key]['tax_amount'] += (($invoice->amount - $invoice->balance) / $invoice->balance) * $tax['total'] ?? 0; } } @@ -129,6 +127,8 @@ class TaxSummaryReport extends BaseExport $this->csv->insertOne([]); $this->csv->insertOne([ctrans('texts.cash_vs_accrual')]); + $this->csv->insertOne($this->buildHeader()); + foreach($accrual_map as $key => $value) { @@ -137,6 +137,7 @@ class TaxSummaryReport extends BaseExport $this->csv->insertOne([]); $this->csv->insertOne([ctrans('texts.cash_accounting')]); + $this->csv->insertOne($this->buildHeader()); foreach($cash_map as $key => $value) { $this->csv->insertOne([$key, Number::formatMoney($value['tax_amount'], $this->company)]); diff --git a/app/Transformers/PurchaseOrderHistoryTransformer.php b/app/Transformers/PurchaseOrderHistoryTransformer.php index 5f2af4d65914..8422ce16d894 100644 --- a/app/Transformers/PurchaseOrderHistoryTransformer.php +++ b/app/Transformers/PurchaseOrderHistoryTransformer.php @@ -19,11 +19,11 @@ class PurchaseOrderHistoryTransformer extends EntityTransformer { use MakesHash; - protected $defaultIncludes = [ + protected array $defaultIncludes = [ // 'activity', ]; - protected $availableIncludes = [ + protected array $availableIncludes = [ 'activity', ]; diff --git a/app/Utils/Ninja.php b/app/Utils/Ninja.php index 9b41b6ab0e65..ce03dfefc3b9 100644 --- a/app/Utils/Ninja.php +++ b/app/Utils/Ninja.php @@ -43,7 +43,7 @@ class Ninja public static function getDebugInfo() { - $mysql_version = DB::select(DB::raw('select version() as version')->getValue(DB::connection()->getQueryGrammar()))[0]->version; + $mysql_version = DB::select('select version() as version')[0]->version; $version = request()->input('version', 'No Version Supplied.'); diff --git a/config/ninja.php b/config/ninja.php index df0105960779..8bf9e3de1475 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -15,8 +15,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION','5.7.6'), - 'app_tag' => env('APP_TAG','5.7.6'), + 'app_version' => env('APP_VERSION','5.7.7'), + 'app_tag' => env('APP_TAG','5.7.7'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), @@ -39,7 +39,7 @@ return [ 'trusted_proxies' => env('TRUSTED_PROXIES', false), 'is_docker' => env('IS_DOCKER', false), 'local_download' => env('LOCAL_DOWNLOAD', false), - 'sentry_dsn' => env('SENTRY_LARAVEL_DSN', null), + 'sentry_dsn' => env('SENTRY_LARAVEL_DSN', "https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co/5"), 'environment' => env('NINJA_ENVIRONMENT', 'selfhost'), // 'hosted', 'development', 'selfhost', 'reseller' 'preconfigured_install' => env('PRECONFIGURED_INSTALL', false), 'update_secret' => env('UPDATE_SECRET', ''), diff --git a/routes/api.php b/routes/api.php index aa4e108a5273..3ce1fdc1737e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -111,6 +111,7 @@ use App\Http\Controllers\Reports\ClientContactReportController; use App\Http\Controllers\Reports\PurchaseOrderReportController; use App\Http\Controllers\Reports\RecurringInvoiceReportController; use App\Http\Controllers\Reports\PurchaseOrderItemReportController; +use App\Http\Controllers\SearchController; Route::group(['middleware' => ['throttle:api', 'api_secret_check']], function () { Route::post('api/v1/signup', [AccountController::class, 'store'])->name('signup.submit'); @@ -317,7 +318,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::post('reports/tax_summary_report', TaxSummaryReportController::class); Route::post('reports/user_sales_report', UserSalesReportController::class); Route::post('reports/preview/{hash}', ReportPreviewController::class); - + Route::post('search', SearchController::class); Route::resource('task_schedulers', TaskSchedulerController::class); Route::post('task_schedulers/bulk', [TaskSchedulerController::class, 'bulk'])->name('task_schedulers.bulk'); diff --git a/tests/Feature/Search/SearchApiTest.php b/tests/Feature/Search/SearchApiTest.php new file mode 100644 index 000000000000..e04804e721b7 --- /dev/null +++ b/tests/Feature/Search/SearchApiTest.php @@ -0,0 +1,61 @@ +makeTestData(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + + $this->withoutExceptionHandling(); + + } + + public function testActivityEntity() + { + + $response = false; + + $data = []; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/search', $data); + + $response->assertStatus(200); + + nlog($response->json()); + + } + +} \ No newline at end of file diff --git a/tests/Unit/CheckDataTest.php b/tests/Unit/CheckDataTest.php new file mode 100644 index 000000000000..2de8f3d26416 --- /dev/null +++ b/tests/Unit/CheckDataTest.php @@ -0,0 +1,285 @@ +faker = \Faker\Factory::create(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + + } + + private function buildData() + { + $this->account = Account::factory()->create([ + 'hosted_client_count' => 1000, + 'hosted_company_count' => 1000, + ]); + + $this->account->num_users = 3; + $this->account->save(); + + $this->user = User::factory()->create([ + 'account_id' => $this->account->id, + 'confirmation_code' => 'xyz123', + 'email' => $this->faker->unique()->safeEmail(), + ]); + + $settings = CompanySettings::defaults(); + $settings->client_online_payment_notification = false; + $settings->client_manual_payment_notification = false; + + $this->company = Company::factory()->create([ + 'account_id' => $this->account->id, + 'settings' => $settings, + ]); + + $this->company->settings = $settings; + $this->company->save(); + + $this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $this->account->id); + $this->cu->is_owner = true; + $this->cu->is_admin = true; + $this->cu->is_locked = false; + $this->cu->save(); + + $this->token = \Illuminate\Support\Str::random(64); + + $company_token = new CompanyToken; + $company_token->user_id = $this->user->id; + $company_token->company_id = $this->company->id; + $company_token->account_id = $this->account->id; + $company_token->name = 'test token'; + $company_token->token = $this->token; + $company_token->is_system = true; + + $company_token->save(); + + $this->client = Client::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'is_deleted' => 0, + 'name' => 'bob', + 'address1' => '1234', + 'balance' => 100, + 'paid_to_date' => 50, + ]); + + ClientContact::factory()->create([ + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + 'is_primary' => 1, + 'first_name' => 'john', + 'last_name' => 'doe', + 'email' => 'john@doe.com' + ]); + + } + + public function testDbQueriesRaw5() + { + $this->buildData(); + + $i = Invoice::factory()->count(5)->create([ + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + ]); + + Invoice::where('status_id', 2)->cursor()->each(function ($i) { + + $i->service()->markPaid()->save(); + + }); + + Payment::with('paymentables')->cursor()->each(function($payment){ + $this->assertNotNull($payment->paymentables()->where('paymentable_type', \App\Models\Credit::class)->get() + ->sum(\DB::raw('amount')->getValue(\DB::connection()->getQueryGrammar()))); + }); + + Payment::with('paymentables')->cursor()->each(function ($payment) { + $this->assertNotNull($payment->paymentables()->where('paymentable_type', \App\Models\Credit::class)->get() + ->sum('amount')); + }); + + $amount = Paymentable::first()->payment->paymentables()->where('paymentable_type', 'invnoices')->get()->sum('amount'); + + $this->assertNotNull($amount); + + } + + public function testDbQueriesRaw4() + { + $this->buildData(); + + ClientContact::factory()->count(10)->create([ + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + ]); + + $clients_refactor = \DB::table('clients') + ->leftJoin('client_contacts', function ($join){ + $join->on('client_contacts.client_id', '=', 'clients.id'); + }) + ->get(['clients.id', \DB::raw('count(client_contacts.id) as contact_count')]); + + // $this->assertNotNull($clients); + $this->assertNotNull($clients_refactor); + + } + + public function testDbQueriesRaw3() + { + $this->buildData(); + + User::factory()->create([ + 'account_id' => $this->account->id, + 'email' => $this->faker->unique()->safeEmail(), + ]); + + User::factory()->create([ + 'account_id' => $this->account->id, + 'email' => $this->faker->unique()->safeEmail(), + ]); + + $user_hash = 'a'; + + $user_count = User::where('account_id', $this->company->account->id) + ->where( + \DB::raw('CONCAT_WS(" ", first_name, last_name)'), + 'like', + '%'.$user_hash.'%' + ) + ->get(); + + $user_count_refactor = User::whereRaw("account_id = ? AND CONCAT_WS(' ', first_name, last_name) like ?", [$this->company->account_id, '%'.$user_hash.'%']) + ->get(); + + + $this->assertEquals($user_count_refactor->count(), $user_count->count()); + } + + public function testDbRawQueries1() + { + $this->buildData(); + + $results = \DB::select(\DB::raw(" + SELECT count(clients.id) as count + FROM clients + ")->getValue(\DB::connection()->getQueryGrammar())); + + + $refactored = \DB::select(" + SELECT count(clients.id) as count + FROM clients + "); + + $this->assertEquals($refactored[0]->count, $results[0]->count); + + } + + public function testDbRawQueries2() + { + $this->buildData(); + + Payment::factory()->count(5)->create([ + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + ]); + + Invoice::factory()->count(5)->create([ + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + ]); + + Invoice::where('status_id', 2)->cursor()->each(function ($i) { + + $i->service()->markPaid()->save(); + + }); + + $results = \DB::select(\DB::raw(" + SELECT + SUM(payments.amount) as amount + FROM payments + LEFT JOIN paymentables + ON + payments.id = paymentables.payment_id + WHERE paymentable_type = ? + AND paymentables.deleted_at is NULL + AND paymentables.amount > 0 + AND payments.is_deleted = 0 + AND payments.client_id = ?; + ")->getValue(\DB::connection()->getQueryGrammar()), ['invoices', $this->client->id]); + + $refactored = \DB::select(" + SELECT + SUM(payments.amount) as amount + FROM payments + LEFT JOIN paymentables + ON + payments.id = paymentables.payment_id + WHERE paymentable_type = ? + AND paymentables.deleted_at is NULL + AND paymentables.amount > 0 + AND payments.is_deleted = 0 + AND payments.client_id = ?; + ", ['invoices', $this->client->id]); + + $this->assertEquals($refactored[0]->amount, $results[0]->amount); + + } + +}