Fixes for conflicts

This commit is contained in:
David Bomba 2023-02-05 15:00:15 +11:00
commit 46b4ccd7e8
228 changed files with 301379 additions and 498735 deletions

View File

@ -1 +1 @@
5.5.64 5.5.67

View File

@ -175,8 +175,6 @@ class CheckData extends Command
}); });
} }
private function checkOauthSanity() private function checkOauthSanity()

View File

@ -442,6 +442,8 @@ class CompanySettings extends BaseSettings
public $send_email_on_mark_paid = false; public $send_email_on_mark_paid = false;
public $postmark_secret = ''; public $postmark_secret = '';
public $custom_sending_email = '';
public $mailgun_secret = ''; public $mailgun_secret = '';
@ -459,7 +461,11 @@ class CompanySettings extends BaseSettings
public $show_shipping_address = false; public $show_shipping_address = false;
public $accept_client_input_quote_approval = false;
public static $casts = [ public static $casts = [
'accept_client_input_quote_approval' => 'bool',
'custom_sending_email' => 'string',
'show_paid_stamp' => 'bool', 'show_paid_stamp' => 'bool',
'show_shipping_address' => 'bool', 'show_shipping_address' => 'bool',
'company_logo_size' => 'string', 'company_logo_size' => 'string',

View File

@ -33,7 +33,6 @@ use PDOException;
use Sentry\Laravel\Integration; use Sentry\Laravel\Integration;
use Sentry\State\Scope; use Sentry\State\Scope;
use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use League\Flysystem\UnableToCreateDirectory; use League\Flysystem\UnableToCreateDirectory;
@ -222,7 +221,7 @@ class Handler extends ExceptionHandler
return response()->json(['message'=>'Too many requests'], 429); return response()->json(['message'=>'Too many requests'], 429);
// } elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) { // } elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
// return response()->json(['message'=>'Fatal error'], 500); //@deprecated // return response()->json(['message'=>'Fatal error'], 500); //@deprecated
} elseif ($exception instanceof AuthorizationException) { } elseif ($exception instanceof AuthorizationException && $request->expectsJson()) {
return response()->json(['message'=> $exception->getMessage()], 401); return response()->json(['message'=> $exception->getMessage()], 401);
} elseif ($exception instanceof TokenMismatchException) { } elseif ($exception instanceof TokenMismatchException) {
return redirect() return redirect()

View File

@ -0,0 +1,33 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Exceptions\Ninja;
use Exception;
class ClientPortalAuthorizationException extends Exception
{
public function report()
{
// ..
}
public function render($request)
{
return view('errors.client-error', [
'account' => auth()->guard('contact')->check() ? auth()->guard('contact')->user()->user->account : false,
'company' => auth()->guard('contact')->check() ? auth()->guard('contact')->user()->company : false,
'title' => ctrans('texts.error_title'),
'message' => $this->getMessage(),
'code' => $this->getCode(),
]);
}
}

View File

@ -26,10 +26,11 @@ class BankIntegrationFilters extends QueryFilters
*/ */
public function name(string $name = ''): Builder public function name(string $name = ''): Builder
{ {
if(strlen($name) >=1) if (strlen($name) == 0) {
return $this->builder->where('bank_account_name', 'like', '%'.$name.'%'); return $this->builder;
}
return $this->builder; return $this->builder->where('bank_account_name', 'like', '%'.$name.'%');
} }
/** /**
@ -90,9 +91,13 @@ class BankIntegrationFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -27,10 +27,11 @@ class BankTransactionFilters extends QueryFilters
*/ */
public function name(string $name = ''): Builder public function name(string $name = ''): Builder
{ {
if(strlen($name) >=1) if (strlen($name) == 0) {
return $this->builder->where('bank_account_name', 'like', '%'.$name.'%'); return $this->builder;
}
return $this->builder;
return $this->builder->where('bank_account_name', 'like', '%'.$name.'%');
} }
/** /**
@ -40,7 +41,7 @@ class BankTransactionFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -66,7 +67,7 @@ class BankTransactionFilters extends QueryFilters
* *
* @return Builder * @return Builder
*/ */
public function client_status(string $value = '') :Builder public function client_status(string $value = ''): Builder
{ {
if (strlen($value) == 0) { if (strlen($value) == 0) {
return $this->builder; return $this->builder;
@ -123,12 +124,13 @@ class BankTransactionFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if(!is_array($sort_col)) if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder; return $this->builder;
}
if($sort_col[0] == 'deposit') if($sort_col[0] == 'deposit')
return $this->builder->where('base_type', 'CREDIT')->orderBy('amount', $sort_col[1]); return $this->builder->where('base_type', 'CREDIT')->orderBy('amount', $sort_col[1]);

View File

@ -11,11 +11,7 @@
namespace App\Filters; namespace App\Filters;
use App\Models\BankTransactionRule;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
/** /**
* BankTransactionRuleilters. * BankTransactionRuleilters.
@ -30,10 +26,11 @@ class BankTransactionRuleFilters extends QueryFilters
*/ */
public function name(string $name = ''): Builder public function name(string $name = ''): Builder
{ {
if(strlen($name) >=1) if (strlen($name) == 0) {
return $this->builder->where('name', 'like', '%'.$name.'%'); return $this->builder;
}
return $this->builder;
return $this->builder->where('name', 'like', '%'.$name.'%');
} }
/** /**
@ -43,7 +40,7 @@ class BankTransactionRuleFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -61,26 +58,17 @@ class BankTransactionRuleFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }
/**
* Returns the base query.
*
* @param int company_id
* @param User $user
* @return Builder
* @deprecated
*/
public function baseQuery(int $company_id, User $user) : Builder
{
}
/** /**
* Filters the query by the users company ID. * Filters the query by the users company ID.
* *

View File

@ -11,11 +11,7 @@
namespace App\Filters; namespace App\Filters;
use App\Models\Client;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
/** /**
* ClientFilters. * ClientFilters.
@ -30,10 +26,11 @@ class ClientFilters extends QueryFilters
*/ */
public function name(string $name = ''): Builder public function name(string $name = ''): Builder
{ {
if(strlen($name) >=1) if (strlen($name) == 0) {
return $this->builder->where('name', 'like', '%'.$name.'%'); return $this->builder;
}
return $this->builder; return $this->builder->where('name', 'like', '%'.$name.'%');
} }
/** /**
@ -42,8 +39,12 @@ class ClientFilters extends QueryFilters
* @param string $balance * @param string $balance
* @return Builder * @return Builder
*/ */
public function balance(string $balance): Builder public function balance(string $balance = ''): Builder
{ {
if (strlen($balance) == 0) {
return $this->builder;
}
$parts = $this->split($balance); $parts = $this->split($balance);
return $this->builder->where('balance', $parts->operator, $parts->value); return $this->builder->where('balance', $parts->operator, $parts->value);
@ -55,27 +56,29 @@ class ClientFilters extends QueryFilters
* @param string balance * @param string balance
* @return Builder * @return Builder
*/ */
public function between_balance(string $balance): Builder public function between_balance(string $balance = ''): Builder
{ {
$parts = explode(':', $balance); $parts = explode(':', $balance);
if (! is_array($parts)) { if (!is_array($parts) || count($parts) != 2) {
return $this->builder; return $this->builder;
} }
return $this->builder->whereBetween('balance', [$parts[0], $parts[1]]); return $this->builder->whereBetween('balance', [$parts[0], $parts[1]]);
} }
public function email(string $email = ''):Builder public function email(string $email = ''): Builder
{ {
return if (strlen($email) == 0) {
return $this->builder;
}
$this->builder->whereHas('contacts', function ($query) use ($email) { return $this->builder->whereHas('contacts', function ($query) use ($email) {
$query->where('email', $email); $query->where('email', $email);
}); });
} }
public function client_id(string $client_id = '') :Builder public function client_id(string $client_id = ''): Builder
{ {
if (strlen($client_id) == 0) { if (strlen($client_id) == 0) {
return $this->builder; return $this->builder;
@ -84,13 +87,21 @@ class ClientFilters extends QueryFilters
return $this->builder->where('id', $this->decodePrimaryKey($client_id)); return $this->builder->where('id', $this->decodePrimaryKey($client_id));
} }
public function id_number(string $id_number = ''):Builder public function id_number(string $id_number = ''): Builder
{ {
if (strlen($id_number) == 0) {
return $this->builder;
}
return $this->builder->where('id_number', $id_number); return $this->builder->where('id_number', $id_number);
} }
public function number(string $number = ''):Builder public function number(string $number = ''): Builder
{ {
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number); return $this->builder->where('number', $number);
} }
@ -101,7 +112,7 @@ class ClientFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -128,10 +139,14 @@ class ClientFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
if($sort_col[0] == 'display_name') if($sort_col[0] == 'display_name')
$sort_col[0] = 'name'; $sort_col[0] = 'name';

View File

@ -11,7 +11,6 @@
namespace App\Filters; namespace App\Filters;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
/** /**
@ -26,7 +25,7 @@ class CompanyGatewayFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -43,10 +42,14 @@ class CompanyGatewayFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -30,7 +30,7 @@ class CreditFilters extends QueryFilters
* @param string credit_status The credit status as seen by the client * @param string credit_status The credit status as seen by the client
* @return Builder * @return Builder
*/ */
public function credit_status(string $value = '') :Builder public function credit_status(string $value = ''): Builder
{ {
if (strlen($value) == 0) { if (strlen($value) == 0) {
return $this->builder; return $this->builder;
@ -66,7 +66,7 @@ class CreditFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -85,16 +85,29 @@ class CreditFilters extends QueryFilters
}); });
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }
@ -123,7 +136,7 @@ class CreditFilters extends QueryFilters
* *
* @return Builder * @return Builder
*/ */
private function contactViewFilter() : Builder private function contactViewFilter(): Builder
{ {
return $this->builder return $this->builder
->whereCompanyId(auth()->guard('contact')->user()->company->id) ->whereCompanyId(auth()->guard('contact')->user()->company->id)

View File

@ -32,7 +32,7 @@ class DesignFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
return $this->builder->where(function ($query) use ($filter) { return $this->builder->where(function ($query) use ($filter) {
$query->where('designs.name', 'like', '%'.$filter.'%'); $query->where('designs.name', 'like', '%'.$filter.'%');
}); });
} }
@ -44,14 +44,15 @@ class DesignFilters extends QueryFilters
* *
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if(is_array($sort_col)) if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder;
}
return $this->builder; return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }
/** /**
@ -61,7 +62,6 @@ class DesignFilters extends QueryFilters
*/ */
public function entityFilter(): Builder public function entityFilter(): Builder
{ {
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
return $this->builder->where('company_id', auth()->user()->company()->id)->orWhere('company_id', null)->orderBy('id','asc'); return $this->builder->where('company_id', auth()->user()->company()->id)->orWhere('company_id', null)->orderBy('id','asc');
} }
} }

View File

@ -39,6 +39,7 @@ class DocumentFilters extends QueryFilters
* Overriding method as client_id does * Overriding method as client_id does
* not exist on this model, just pass * not exist on this model, just pass
* back the builder * back the builder
*
* @param string $client_id The client hashed id. * @param string $client_id The client hashed id.
* *
* @return Builder * @return Builder
@ -54,14 +55,15 @@ class DocumentFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort = '') : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if(is_array($sort_col)) if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder;
}
return $this->builder; return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -25,7 +25,7 @@ class ExpenseCategoryFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -41,10 +41,14 @@ class ExpenseCategoryFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['name'])) if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['name']))
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);

View File

@ -25,7 +25,7 @@ class ExpenseFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -53,7 +53,7 @@ class ExpenseFilters extends QueryFilters
* *
* @return Builder * @return Builder
*/ */
public function client_status(string $value = '') :Builder public function client_status(string $value = ''): Builder
{ {
if (strlen($value) == 0) { if (strlen($value) == 0) {
return $this->builder; return $this->builder;
@ -132,16 +132,29 @@ class ExpenseFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) { if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -179,8 +179,7 @@ class InvoiceFilters extends QueryFilters
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
//catch invalid explode array count if (!is_array($sort_col) || count($sort_col) != 2) {
if (count($sort_col) == 1) {
return $this->builder; return $this->builder;
} }
@ -224,7 +223,7 @@ class InvoiceFilters extends QueryFilters
* *
* @return Builder * @return Builder
*/ */
private function contactViewFilter() : Builder private function contactViewFilter(): Builder
{ {
return $this->builder return $this->builder
->whereCompanyId(auth()->guard('contact')->user()->company->id) ->whereCompanyId(auth()->guard('contact')->user()->company->id)

View File

@ -62,25 +62,30 @@ class PaymentFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if(is_array($sort_col)) if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder;
}
return true; return $this->builder->orderBy($sort_col[0], $sort_col[1]);
}
public function number(string $number = ''): Builder
{
return $this->builder->where('number', $number);
} }
/** /**

View File

@ -42,10 +42,14 @@ class PaymentTermFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -58,12 +58,13 @@ class ProductFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if(!is_array($sort_col)) if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder; return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -25,7 +25,7 @@ class ProjectFilters extends QueryFilters
* @return Illuminate\Eloquent\Query\Builder * @return Illuminate\Eloquent\Query\Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') :Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -37,6 +37,15 @@ class ProjectFilters extends QueryFilters
->orWhere('private_notes', 'like', '%'.$filter.'%'); ->orWhere('private_notes', 'like', '%'.$filter.'%');
}); });
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
@ -44,10 +53,14 @@ class ProjectFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Illuminate\Eloquent\Query\Builder * @return Illuminate\Eloquent\Query\Builder
*/ */
public function sort(string $sort) :Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
if(is_array($sort_col)) if(is_array($sort_col))
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }
@ -57,7 +70,7 @@ class ProjectFilters extends QueryFilters
* *
* @return Illuminate\Eloquent\Query\Builder * @return Illuminate\Eloquent\Query\Builder
*/ */
public function entityFilter() :Builder public function entityFilter(): Builder
{ {
return $this->builder->company(); return $this->builder->company();
} }

View File

@ -100,16 +100,29 @@ class PurchaseOrderFilters extends QueryFilters
}); });
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }
@ -136,7 +149,7 @@ class PurchaseOrderFilters extends QueryFilters
* *
* @return Builder * @return Builder
*/ */
private function contactViewFilter() : Builder private function contactViewFilter(): Builder
{ {
return $this->builder return $this->builder
->whereCompanyId(auth()->guard('contact')->user()->company->id) ->whereCompanyId(auth()->guard('contact')->user()->company->id)

View File

@ -136,7 +136,7 @@ abstract class QueryFilters
* @param string filter * @param string filter
* @return Builder * @return Builder
*/ */
public function status(string $filter = '') : Builder public function status(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -241,7 +241,7 @@ abstract class QueryFilters
return $this->builder->where('is_deleted', $value); return $this->builder->where('is_deleted', $value);
} }
public function client_id(string $client_id = '') :Builder public function client_id(string $client_id = ''): Builder
{ {
if (strlen($client_id) == 0) { if (strlen($client_id) == 0) {
return $this->builder; return $this->builder;
@ -250,7 +250,7 @@ abstract class QueryFilters
return $this->builder->where('client_id', $this->decodePrimaryKey($client_id)); return $this->builder->where('client_id', $this->decodePrimaryKey($client_id));
} }
public function vendor_id(string $vendor_id = '') :Builder public function vendor_id(string $vendor_id = ''): Builder
{ {
if (strlen($vendor_id) == 0) { if (strlen($vendor_id) == 0) {
return $this->builder; return $this->builder;

View File

@ -113,7 +113,11 @@ class QuoteFilters extends QueryFilters
public function number($number = ''): Builder public function number($number = ''): Builder
{ {
return $this->builder->where('number', 'like', '%'.$number.'%'); if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
} }
/** /**
@ -122,10 +126,14 @@ class QuoteFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
if($sort_col[0] == 'valid_until') if($sort_col[0] == 'valid_until')
$sort_col[0] = 'due_date'; $sort_col[0] = 'due_date';

View File

@ -40,16 +40,29 @@ class RecurringExpenseFilters extends QueryFilters
}); });
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -83,16 +83,29 @@ class RecurringInvoiceFilters extends QueryFilters
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -39,16 +39,29 @@ class RecurringQuoteFilters extends QueryFilters
}); });
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Illuminate\Database\Eloquent\Builder * @return Illuminate\Database\Eloquent\Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -42,10 +42,14 @@ class SubscriptionFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -18,18 +18,30 @@ use Illuminate\Database\Eloquent\Builder;
*/ */
class SystemLogFilters extends QueryFilters class SystemLogFilters extends QueryFilters
{ {
public function type_id(int $type_id) :Builder public function type_id(string $type_id = ''): Builder
{ {
if (strlen($type_id) == 0) {
return $this->builder;
}
return $this->builder->where('type_id', $type_id); return $this->builder->where('type_id', $type_id);
} }
public function category_id(int $category_id) :Builder public function category_id(string $category_id = ''): Builder
{ {
if (strlen($category_id) == 0) {
return $this->builder;
}
return $this->builder->where('category_id', $category_id); return $this->builder->where('category_id', $category_id);
} }
public function event_id(int $event_id) :Builder public function event_id(string $event_id = ''): Builder
{ {
if (strlen($event_id) == 0) {
return $this->builder;
}
return $this->builder->where('event_id', $event_id); return $this->builder->where('event_id', $event_id);
} }
@ -40,7 +52,7 @@ class SystemLogFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -55,10 +67,14 @@ class SystemLogFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort) : Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -81,6 +81,15 @@ class TaskFilters extends QueryFilters
return $this->builder->where('project_id', $this->decodePrimaryKey($project)); return $this->builder->where('project_id', $this->decodePrimaryKey($project));
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
@ -88,10 +97,14 @@ class TaskFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -42,10 +42,14 @@ class TaskStatusFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -25,7 +25,7 @@ class TaxRateFilters extends QueryFilters
* @return Builder * @return Builder
* @deprecated * @deprecated
*/ */
public function filter(string $filter = '') : Builder public function filter(string $filter = ''): Builder
{ {
if (strlen($filter) == 0) { if (strlen($filter) == 0) {
return $this->builder; return $this->builder;
@ -42,10 +42,14 @@ class TaxRateFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -42,10 +42,14 @@ class TokenFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -46,10 +46,14 @@ class UserFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }
@ -76,8 +80,9 @@ class UserFilters extends QueryFilters
public function with(string $value = ''): Builder public function with(string $value = ''): Builder
{ {
if(strlen($value) == 0) if(strlen($value) == 0) {
return $this->builder; return $this->builder;
}
return $this->builder return $this->builder
->orWhere($this->with_property, $value) ->orWhere($this->with_property, $value)

View File

@ -46,16 +46,29 @@ class VendorFilters extends QueryFilters
}); });
} }
public function number(string $number = ''): Builder
{
if (strlen($number) == 0) {
return $this->builder;
}
return $this->builder->where('number', $number);
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -42,10 +42,14 @@ class WebhookFilters extends QueryFilters
* @param string sort formatted as column|asc * @param string sort formatted as column|asc
* @return Builder * @return Builder
*/ */
public function sort(string $sort): Builder public function sort(string $sort = ''): Builder
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
return $this->builder->orderBy($sort_col[0], $sort_col[1]); return $this->builder->orderBy($sort_col[0], $sort_col[1]);
} }

View File

@ -73,7 +73,6 @@ class GmailTransport extends AbstractTransport
/* Need to slow down */ /* Need to slow down */
if($e->getCode() == '429') { if($e->getCode() == '429') {
sleep(rand(5,10));
nlog("429 google - retrying "); nlog("429 google - retrying ");
$service->users_messages->send('me', $body, []); $service->users_messages->send('me', $body, []);

View File

@ -291,11 +291,11 @@ class LoginController extends BaseController
return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400); return response()->json(['message' => 'User found, but not attached to any companies, please see your administrator'], 400);
} }
$cu->first()->account->companies->each(function ($company) use ($cu, $request) { // $cu->first()->account->companies->each(function ($company) use ($cu, $request) {
if ($company->tokens()->where('is_system', true)->count() == 0) { // if ($company->tokens()->where('is_system', true)->count() == 0) {
(new CreateCompanyToken($company, $cu->first()->user, $request->server('HTTP_USER_AGENT')))->handle(); // (new CreateCompanyToken($company, $cu->first()->user, $request->server('HTTP_USER_AGENT')))->handle();
} // }
}); // });
if ($request->has('current_company') && $request->input('current_company') == 'true') { if ($request->has('current_company') && $request->input('current_company') == 'true') {
$cu->where('company_id', $company_token->company_id); $cu->where('company_id', $company_token->company_id);
@ -480,13 +480,13 @@ class LoginController extends BaseController
return $cu; return $cu;
} }
if (auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count()) { // if (auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count()) {
auth()->user()->companies->each(function ($company) { // auth()->user()->companies->each(function ($company) {
if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->exists()) { // if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->exists()) {
(new CreateCompanyToken($company, auth()->user(), 'Google_O_Auth'))->handle(); // (new CreateCompanyToken($company, auth()->user(), 'Google_O_Auth'))->handle();
} // }
}); // });
} // }
$truth->setCompanyToken(CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $set_company->id)->first()); $truth->setCompanyToken(CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $set_company->id)->first());

View File

@ -267,7 +267,7 @@ class BaseController extends Controller
$updated_at = request()->has('updated_at') ? request()->input('updated_at') : 0; $updated_at = request()->has('updated_at') ? request()->input('updated_at') : 0;
if ($user->getCompany()->is_large && $updated_at == 0 && $this->complexPermissionsUser()) { if ($user->getCompany()->is_large && $updated_at == 0) {
$updated_at = time(); $updated_at = time();
} }
@ -633,7 +633,7 @@ class BaseController extends Controller
{ {
$user = auth()->user(); $user = auth()->user();
if ($user->getCompany()->is_large || $this->complexPermissionsUser()) { if ($user->getCompany()->is_large) {
$this->manager->parseIncludes($this->mini_load); $this->manager->parseIncludes($this->mini_load);
return $this->miniLoadResponse($query); return $this->miniLoadResponse($query);
@ -859,7 +859,7 @@ class BaseController extends Controller
'company.bank_transactions'=> function ($query) use ($created_at, $user) { 'company.bank_transactions'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at); $query->where('created_at', '>=', $created_at);
if (! $user->hasPermission('bank_transactions')) { if (! $user->hasPermission('bank_transaction')) {
$query->where('bank_transactions.user_id', $user->id); $query->where('bank_transactions.user_id', $user->id);
} }
}, },

View File

@ -110,7 +110,6 @@ class EntityViewController extends Controller
$key = $entity_type.'_id'; $key = $entity_type.'_id';
$invitation = $invitation_entity::where('key', $invitation_key)->firstOrFail(); $invitation = $invitation_entity::where('key', $invitation_key)->firstOrFail();
// $invitation = $invitation_entity::whereRaw('BINARY `key`= ?', [$invitation_key])->firstOrFail();
$contact = $invitation->contact; $contact = $invitation->contact;
@ -141,7 +140,7 @@ class EntityViewController extends Controller
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
}) })
->with('contact.client') ->with('contact.client')
->first(); ->firstOrFail();
$contact = $invitation->contact; $contact = $invitation->contact;
$contact->password = Hash::make($request->password); $contact->password = Hash::make($request->password);

View File

@ -149,12 +149,18 @@ class PaymentController extends Controller
$payment = $payment->service()->applyCredits($payment_hash)->save(); $payment = $payment->service()->applyCredits($payment_hash)->save();
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id'))); $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')));
$invoices->each(function ($i){
$i->is_proforma = false;
$i->saveQuietly();
});
event('eloquent.created: App\Models\Payment', $payment); event('eloquent.created: App\Models\Payment', $payment);
if($invoices->sum('balance') > 0){ if($invoices->sum('balance') > 0){
$invoice = $invoices->first(); $invoice = $invoices->first();
$invoice->service()->touchPdf(true);
return redirect()->route('client.invoice.show', ['invoice' => $invoice->hashed_id, 'hash' => $request->input('hash')]); return redirect()->route('client.invoice.show', ['invoice' => $invoice->hashed_id, 'hash' => $request->input('hash')]);
} }

View File

@ -81,6 +81,7 @@ class QuoteController extends Controller
public function bulk(ProcessQuotesInBulkRequest $request) public function bulk(ProcessQuotesInBulkRequest $request)
{ {
$transformed_ids = $this->transformKeys($request->quotes); $transformed_ids = $this->transformKeys($request->quotes);
nlog(request()->all());
if ($request->action == 'download') { if ($request->action == 'download') {
return $this->downloadQuotes((array) $transformed_ids); return $this->downloadQuotes((array) $transformed_ids);
@ -180,6 +181,14 @@ class QuoteController extends Controller
if ($process) { if ($process) {
foreach ($quotes as $quote) { foreach ($quotes as $quote) {
if(request()->has('user_input') && strlen(request()->input('user_input')) > 2) {
$quote->public_notes .= $quote->public_notes . "\n" . request()->input('user_input');
$quote->saveQuietly();
}
$quote->service()->approve(auth()->user())->save(); $quote->service()->approve(auth()->user())->save();
if (request()->has('signature') && ! is_null(request()->signature) && ! empty(request()->signature)) { if (request()->has('signature') && ! is_null(request()->signature) && ! empty(request()->signature)) {

View File

@ -55,4 +55,9 @@ class SubscriptionPlanSwitchController extends Controller
]); ]);
} }
public function not_availabe()
{
abort(404, 'ewwo');
}
} }

View File

@ -494,7 +494,7 @@ class CompanyController extends BaseController
$account->delete(); $account->delete();
if (Ninja::isHosted()) { if (Ninja::isHosted()) {
\Modules\Admin\Jobs\Account\NinjaDeletedAccount::dispatch($account_key, $request->all()); \Modules\Admin\Jobs\Account\NinjaDeletedAccount::dispatch($account_key, $request->all(), auth()->user()->email);
} }
LightLogs::create(new AccountDeleted()) LightLogs::create(new AccountDeleted())

View File

@ -642,10 +642,57 @@ class CreditController extends BaseController
} }
} }
/**
* @OA\Get(
* path="/api/v1/credit/{invitation_key}/download",
* operationId="downloadCredit",
* tags={"quotes"},
* summary="Download a specific credit by invitation key",
* description="Downloads a specific quote",
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="invitation_key",
* in="path",
* description="The Credit Invitation Key",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns the credit pdf",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
* @param $invitation_key
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPdf($invitation_key) public function downloadPdf($invitation_key)
{ {
$invitation = $this->credit_repository->getInvitationByKey($invitation_key); $invitation = $this->credit_repository->getInvitationByKey($invitation_key);
if (! $invitation) {
return response()->json(['message' => 'no record found'], 400);
}
$credit = $invitation->credit; $credit = $invitation->credit;
$file = $credit->service()->getCreditPdf($invitation); $file = $credit->service()->getCreditPdf($invitation);

View File

@ -277,6 +277,8 @@ class ExpenseController extends BaseController
event(new ExpenseWasUpdated($expense, $expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new ExpenseWasUpdated($expense, $expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event('eloquent.updated: App\Models\Expense', $expense);
return $this->itemResponse($expense->fresh()); return $this->itemResponse($expense->fresh());
} }
@ -369,6 +371,8 @@ class ExpenseController extends BaseController
event(new ExpenseWasCreated($expense, $expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new ExpenseWasCreated($expense, $expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event('eloquent.created: App\Models\Expense', $expense);
return $this->itemResponse($expense); return $this->itemResponse($expense);
} }

View File

@ -422,16 +422,6 @@ class InvoiceController extends BaseController
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
// $transaction = [
// 'invoice' => $invoice->transaction_event(),
// 'payment' => [],
// 'client' => $invoice->client->transaction_event(),
// 'credit' => [],
// 'metadata' => [],
// ];
// TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
return $this->itemResponse($invoice); return $this->itemResponse($invoice);
} }

View File

@ -205,6 +205,8 @@ class PaymentController extends BaseController
{ {
$payment = $this->payment_repo->save($request->all(), PaymentFactory::create(auth()->user()->company()->id, auth()->user()->id)); $payment = $this->payment_repo->save($request->all(), PaymentFactory::create(auth()->user()->company()->id, auth()->user()->id));
event('eloquent.created: App\Models\Payment', $payment);
return $this->itemResponse($payment); return $this->itemResponse($payment);
} }
@ -378,6 +380,8 @@ class PaymentController extends BaseController
event(new PaymentWasUpdated($payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new PaymentWasUpdated($payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event('eloquent.updated: App\Models\Payment', $payment);
return $this->itemResponse($payment); return $this->itemResponse($payment);
} }

View File

@ -262,12 +262,14 @@ class ProjectController extends BaseController
$project->fill($request->all()); $project->fill($request->all());
$project->number = empty($project->number) ? $this->getNextProjectNumber($project) : $project->number; $project->number = empty($project->number) ? $this->getNextProjectNumber($project) : $project->number;
$project->save(); $project->saveQuietly();
if ($request->has('documents')) { if ($request->has('documents')) {
$this->saveDocuments($request->input('documents'), $project); $this->saveDocuments($request->input('documents'), $project);
} }
event('eloquent.updated: App\Models\Project', $project);
return $this->itemResponse($project->fresh()); return $this->itemResponse($project->fresh());
} }
@ -358,17 +360,19 @@ class ProjectController extends BaseController
{ {
$project = ProjectFactory::create(auth()->user()->company()->id, auth()->user()->id); $project = ProjectFactory::create(auth()->user()->company()->id, auth()->user()->id);
$project->fill($request->all()); $project->fill($request->all());
$project->save(); $project->saveQuietly();
if (empty($project->number)) { if (empty($project->number)) {
$project->number = $this->getNextProjectNumber($project); $project->number = $this->getNextProjectNumber($project);
$project->save(); $project->saveQuietly();
} }
if ($request->has('documents')) { if ($request->has('documents')) {
$this->saveDocuments($request->input('documents'), $project); $this->saveDocuments($request->input('documents'), $project);
} }
event('eloquent.created: App\Models\Project', $project);
return $this->itemResponse($project->fresh()); return $this->itemResponse($project->fresh());
} }

View File

@ -762,4 +762,74 @@ class PurchaseOrderController extends BaseController
} }
/**
* @OA\Get(
* path="/api/v1/purchase_order/{invitation_key}/download",
* operationId="downloadPurchaseOrder",
* tags={"purchase_orders"},
* summary="Download a specific purchase order by invitation key",
* description="Downloads a specific purchase order",
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="invitation_key",
* in="path",
* description="The Purchase Order Invitation Key",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns the Purchase Order pdf",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
* @param $invitation_key
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPdf($invitation_key)
{
$invitation = $this->purchase_order_repository->getInvitationByKey($invitation_key);
if (! $invitation) {
return response()->json(['message' => 'no record found'], 400);
}
$purchase_order = $invitation->purchase_order;
$file = $purchase_order->service()->getPurchaseOrderPdf();
$headers = ['Content-Type' => 'application/pdf'];
if (request()->input('inline') == 'true') {
$headers = array_merge($headers, ['Content-Disposition' => 'inline']);
}
return response()->streamDownload(function () use ($file) {
echo Storage::get($file);
}, basename($file), $headers);
}
} }

View File

@ -779,9 +779,58 @@ class QuoteController extends BaseController
} }
} }
/**
* @OA\Get(
* path="/api/v1/quote/{invitation_key}/download",
* operationId="downloadQuote",
* tags={"quotes"},
* summary="Download a specific quote by invitation key",
* description="Downloads a specific quote",
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),
* @OA\Parameter(
* name="invitation_key",
* in="path",
* description="The Quote Invitation Key",
* example="D2J234DFA",
* required=true,
* @OA\Schema(
* type="string",
* format="string",
* ),
* ),
* @OA\Response(
* response=200,
* description="Returns the quote pdf",
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
*
* ),
* @OA\Response(
* response="default",
* description="Unexpected Error",
* @OA\JsonContent(ref="#/components/schemas/Error"),
* ),
* )
* @param $invitation_key
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPdf($invitation_key) public function downloadPdf($invitation_key)
{ {
$invitation = $this->quote_repo->getInvitationByKey($invitation_key); $invitation = $this->quote_repo->getInvitationByKey($invitation_key);
if (! $invitation) {
return response()->json(['message' => 'no record found'], 400);
}
$contact = $invitation->contact; $contact = $invitation->contact;
$quote = $invitation->quote; $quote = $invitation->quote;

View File

@ -283,6 +283,8 @@ class TaskController extends BaseController
event(new TaskWasUpdated($task, $task->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new TaskWasUpdated($task, $task->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event('eloquent.updated: App\Models\Task', $task);
return $this->itemResponse($task->fresh()); return $this->itemResponse($task->fresh());
} }
@ -376,6 +378,9 @@ class TaskController extends BaseController
event(new TaskWasCreated($task, $task->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new TaskWasCreated($task, $task->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event('eloquent.created: App\Models\Task', $task);
return $this->itemResponse($task); return $this->itemResponse($task);
} }

View File

@ -276,6 +276,8 @@ class VendorController extends BaseController
event(new VendorWasUpdated($vendor, $vendor->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new VendorWasUpdated($vendor, $vendor->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event('eloquent.updated: App\Models\Vendor', $vendor);
return $this->itemResponse($vendor->fresh()); return $this->itemResponse($vendor->fresh());
} }
@ -372,6 +374,8 @@ class VendorController extends BaseController
event(new VendorWasCreated($vendor, $vendor->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new VendorWasCreated($vendor, $vendor->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
event('eloquent.created: App\Models\Vendor', $vendor);
return $this->itemResponse($vendor); return $this->itemResponse($vendor);
} }

View File

@ -52,6 +52,7 @@ class InvoicesTable extends Component
$query = Invoice::query() $query = Invoice::query()
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
->where('is_deleted', false) ->where('is_deleted', false)
->where('is_proforma', false)
->with('client.gateway_tokens', 'client.contacts') ->with('client.gateway_tokens', 'client.contacts')
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc'); ->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc');

View File

@ -15,12 +15,35 @@ namespace App\Http\Livewire;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\ClientContact; use App\Models\ClientContact;
use App\Models\CompanyGateway; use App\Models\CompanyGateway;
use App\Models\Invoice;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
class RequiredClientInfo extends Component class RequiredClientInfo extends Component
{ {
use MakesHash;
/**
* @var bool
*/
public $show_terms = false;
/**
* @var array
*/
public $invoice;
/**
* @var bool
*/
public $terms_accepted = true;
/**
* @var array
*/
public $fields = []; public $fields = [];
/** /**
@ -28,6 +51,9 @@ class RequiredClientInfo extends Component
*/ */
public $contact; public $contact;
/**
* @var Client
*/
public $client; public $client;
/** /**
@ -60,6 +86,11 @@ class RequiredClientInfo extends Component
'client_shipping_postal_code' => 'shipping_postal_code', 'client_shipping_postal_code' => 'shipping_postal_code',
'client_shipping_country_id' => 'shipping_country_id', 'client_shipping_country_id' => 'shipping_country_id',
'client_custom_value1' => 'custom_value1',
'client_custom_value2' => 'custom_value2',
'client_custom_value3' => 'custom_value3',
'client_custom_value4' => 'custom_value4',
'contact_first_name' => 'first_name', 'contact_first_name' => 'first_name',
'contact_last_name' => 'last_name', 'contact_last_name' => 'last_name',
'contact_email' => 'email', 'contact_email' => 'email',
@ -100,6 +131,10 @@ class RequiredClientInfo extends Component
'client.name' => '', 'client.name' => '',
'client.website' => '', 'client.website' => '',
'client.phone' => '', 'client.phone' => '',
'client.custom_value1' => '',
'client.custom_value2' => '',
'client.custom_value3' => '',
'client.custom_value4' => '',
]; ];
public $show_form = false; public $show_form = false;
@ -114,9 +149,28 @@ class RequiredClientInfo extends Component
$this->client = $this->contact->client; $this->client = $this->contact->client;
count($this->fields) > 0 if($this->company->settings->show_accept_invoice_terms && request()->query('hash'))
{
$this->show_terms = true;
$this->terms_accepted = false;
$this->show_form = true;
$hash = Cache::get(request()->input('hash'));
$this->invoice = Invoice::find($this->decodePrimaryKey($hash['invoice_id']));
}
count($this->fields) > 0 || $this->show_terms
? $this->checkFields() ? $this->checkFields()
: $this->show_form = false; : $this->show_form = false;
}
public function toggleTermsAccepted()
{
$this->terms_accepted = !$this->terms_accepted;
} }
public function handleSubmit(array $data): bool public function handleSubmit(array $data): bool
@ -155,7 +209,7 @@ class RequiredClientInfo extends Component
private function updateClientDetails(array $data): bool private function updateClientDetails(array $data): bool
{ {
nlog($this->company->id);
$client = []; $client = [];
$contact = []; $contact = [];
@ -215,6 +269,7 @@ class RequiredClientInfo extends Component
} }
} }
} }
} }
public function showCopyBillingCheckbox(): bool public function showCopyBillingCheckbox(): bool

View File

@ -23,7 +23,7 @@ class ShowActivityRequest extends Request
*/ */
public function authorize() : bool public function authorize() : bool
{ {
return auth()->user()->isAdmin(); // return auth()->user()->isAdmin();
// return auth()->user()->can('view', Activity::class); return auth()->user()->can('view', Activity::class);
} }
} }

View File

@ -1,14 +1,21 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Requests\ClientPortal\Subscriptions; namespace App\Http\Requests\ClientPortal\Subscriptions;
use App\Models\Subscription; use App\Exceptions\Ninja\ClientPortalAuthorizationException;
use App\Utils\Traits\MakesHash;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
class ShowPlanSwitchRequest extends FormRequest class ShowPlanSwitchRequest extends FormRequest
{ {
use MakesHash;
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
@ -31,4 +38,11 @@ class ShowPlanSwitchRequest extends FormRequest
// //
]; ];
} }
protected function failedAuthorization()
{
throw new ClientPortalAuthorizationException('Unable to change plans due to a restriction on this product.', 400);
}
} }

View File

@ -227,6 +227,8 @@ class BaseImport
]; ];
nlog("Ingest {$ex->getMessage()}"); nlog("Ingest {$ex->getMessage()}");
nlog($record);
} }
} }
@ -368,7 +370,7 @@ class BaseImport
$payment_data['invoices'] = [ $payment_data['invoices'] = [
[ [
'invoice_id' => $invoice->id, 'invoice_id' => $invoice->id,
'amount' => $payment_data['amount'] ?? null, 'amount' => min($invoice->amount, $payment_data['amount']) ?? null,
], ],
]; ];

View File

@ -68,6 +68,11 @@ class BaseTransformer
} }
public function getInvoiceTypeId($data, $field)
{
return isset($data[$field]) && $data[$field] ? (string)$data[$field] : '1';
}
public function getNumber($data, $field) public function getNumber($data, $field)
{ {
return (isset($data->$field) && $data->$field) ? (int)$data->$field : 0; return (isset($data->$field) && $data->$field) ? (int)$data->$field : 0;

View File

@ -222,9 +222,10 @@ class InvoiceTransformer extends BaseTransformer
$record, $record,
'item.custom_value4' 'item.custom_value4'
), ),
'type_id' => '1', //$this->getInvoiceTypeId( $record, 'item.type_id' ), 'type_id' => $this->getInvoiceTypeId( $record, 'item.type_id' ),
]; ];
} }
$transformed['line_items'] = $line_items; $transformed['line_items'] = $line_items;
return $transformed; return $transformed;

View File

@ -52,17 +52,6 @@ class VendorTransformer extends BaseTransformer
'custom_value2' => $this->getString($data, 'vendor.custom_value2'), 'custom_value2' => $this->getString($data, 'vendor.custom_value2'),
'custom_value3' => $this->getString($data, 'vendor.custom_value3'), 'custom_value3' => $this->getString($data, 'vendor.custom_value3'),
'custom_value4' => $this->getString($data, 'vendor.custom_value4'), 'custom_value4' => $this->getString($data, 'vendor.custom_value4'),
// 'vendor_contacts' => [
// [
// 'first_name' => $this->getString(
// $data,
// 'vendor.first_name'
// ),
// 'last_name' => $this->getString($data, 'vendor.last_name'),
// 'email' => $this->getString($data, 'vendor.email'),
// 'phone' => $this->getString($data, 'vendor.phone'),
// ],
// ],
'contacts' => [ 'contacts' => [
[ [
'first_name' => $this->getString( 'first_name' => $this->getString(
@ -70,7 +59,7 @@ class VendorTransformer extends BaseTransformer
'contact.first_name' 'contact.first_name'
), ),
'last_name' => $this->getString($data, 'contact.last_name'), 'last_name' => $this->getString($data, 'contact.last_name'),
'email' => $this->getString($data, 'contact.email'), 'email' => strlen($this->getString($data, 'contact.email')) > 1 ? $this->getString($data, 'contact.email') : $this->getString($data, 'vendor.email'),
'phone' => $this->getString($data, 'contact.phone'), 'phone' => $this->getString($data, 'contact.phone'),
'custom_value1' => $this->getString( 'custom_value1' => $this->getString(
$data, $data,

View File

@ -115,6 +115,7 @@ class CreateAccount
$spafe62e = isset($this->request['token_name']) ? $this->request['token_name'] : request()->server('HTTP_USER_AGENT'); $spafe62e = isset($this->request['token_name']) ? $this->request['token_name'] : request()->server('HTTP_USER_AGENT');
$sp2d97e8 = (new CreateCompanyToken($sp035a66, $spaa9f78, $spafe62e))->handle(); $sp2d97e8 = (new CreateCompanyToken($sp035a66, $spaa9f78, $spafe62e))->handle();
if ($spaa9f78) { if ($spaa9f78) {
event(new AccountCreated($spaa9f78, $sp035a66, Ninja::eventVars())); event(new AccountCreated($spaa9f78, $sp035a66, Ninja::eventVars()));
} }

View File

@ -160,9 +160,5 @@ class AdjustProductInventory implements ShouldQueue
}); });
// $nmo->to_user = $this->company->owner();
// NinjaMailerJob::dispatch($nmo);
} }
} }

View File

@ -75,7 +75,7 @@ class NinjaMailerJob implements ShouldQueue
public function backoff() public function backoff()
{ {
return [30, 60, 180, 240]; return [5, 10, 30, 240];
} }
public function handle() public function handle()
@ -176,19 +176,15 @@ class NinjaMailerJob implements ShouldQueue
* this merges a text string with a json object * this merges a text string with a json object
* need to harvest the ->Message property using the following * need to harvest the ->Message property using the following
*/ */
if($e instanceof ClientException) if(stripos($e->getMessage(), 'code 406') || stripos($e->getMessage(), 'code 300') || stripos($e->getMessage(), 'code 413'))
{ {
$response = $e->getResponse(); $message = "Either Attachment too large, or recipient has been suppressed.";
$message_body = json_decode($response->getBody()->getContents());
if($message_body && property_exists($message_body, 'Message')){
$message = $message_body->Message;
}
/*Do not retry if this is a postmark specific issue such as invalid recipient. */
$this->fail(); $this->fail();
$this->logMailError($e->getMessage(), $this->company->clients()->first());
$this->cleanUpMailers(); $this->cleanUpMailers();
return; return;
} }
@ -382,12 +378,14 @@ class NinjaMailerJob implements ShouldQueue
return $this->setMailDriver(); return $this->setMailDriver();
} }
$user = $this->resolveSendingUser(); $user = $this->resolveSendingUser();
$sending_email = (isset($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
$sending_user = (isset($this->nmo->settings->email_from_name) && strlen($this->nmo->settings->email_from_name) > 2) ? $this->nmo->settings->email_from_name : $user->name();
$this->nmo $this->nmo
->mailable ->mailable
->from($user->email, $user->name()); ->from($sending_email, $sending_user);
} }
/** /**
@ -406,9 +404,12 @@ class NinjaMailerJob implements ShouldQueue
$user = $this->resolveSendingUser(); $user = $this->resolveSendingUser();
$sending_email = (isset($this->nmo->settings->custom_sending_email) && stripos($this->nmo->settings->custom_sending_email, "@")) ? $this->nmo->settings->custom_sending_email : $user->email;
$sending_user = (isset($this->nmo->settings->email_from_name) && strlen($this->nmo->settings->email_from_name) > 2) ? $this->nmo->settings->email_from_name : $user->name();
$this->nmo $this->nmo
->mailable ->mailable
->from($user->email, $user->name()); ->from($sending_email, $sending_user);
} }
/** /**
@ -445,7 +446,6 @@ class NinjaMailerJob implements ShouldQueue
$message->getHeaders()->addTextHeader('gmailtoken', $token); $message->getHeaders()->addTextHeader('gmailtoken', $token);
}); });
sleep(rand(1,3));
} }
/** /**
@ -472,7 +472,6 @@ class NinjaMailerJob implements ShouldQueue
$google->getClient()->setAccessToken(json_encode($user->oauth_user_token)); $google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
sleep(rand(1,6));
} }
catch(\Exception $e) { catch(\Exception $e) {
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first()); $this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
@ -649,8 +648,9 @@ class NinjaMailerJob implements ShouldQueue
public function failed($exception = null) public function failed($exception = null)
{ {
if($exception)
nlog($exception->getMessage()); config(['queue.failed.driver' => null]);
} }
} }

View File

@ -12,6 +12,7 @@
namespace App\Jobs\Ninja; namespace App\Jobs\Ninja;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Account;
use App\Models\Client; use App\Models\Client;
use App\Models\Company; use App\Models\Company;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
@ -43,7 +44,7 @@ class CompanySizeCheck implements ShouldQueue
{ {
if (! config('ninja.db.multi_db_enabled')) { if (! config('ninja.db.multi_db_enabled')) {
Company::where('is_large', false)->withCount(['invoices', 'clients', 'products'])->cursor()->each(function ($company) { Company::where('is_large', false)->withCount(['invoices', 'clients', 'products', 'quotes'])->cursor()->each(function ($company) {
if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500) { if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500) {
nlog("Marking company {$company->id} as large"); nlog("Marking company {$company->id} as large");
@ -62,6 +63,22 @@ class CompanySizeCheck implements ShouldQueue
}); });
/* Ensures lower permissioned users return the correct dataset and refresh responses */
Account::whereHas('companies', function ($query){
$query->where('is_large',0);
})
->whereHas('company_users', function ($query){
$query->where('is_admin', 0);
})
->cursor()->each(function ($account){
$account->companies()->update(['is_large' => true]);
});
} else { } else {
//multiDB environment, need to //multiDB environment, need to
foreach (MultiDB::$dbs as $db) { foreach (MultiDB::$dbs as $db) {
@ -69,8 +86,8 @@ class CompanySizeCheck implements ShouldQueue
nlog("Company size check db {$db}"); nlog("Company size check db {$db}");
Company::where('is_large', false)->withCount(['invoices', 'clients', 'products'])->cursor()->each(function ($company) { Company::where('is_large', false)->withCount(['invoices', 'clients', 'products', 'quotes'])->cursor()->each(function ($company) {
if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500) { if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500 || $company->quotes_count > 500) {
nlog("Marking company {$company->id} as large"); nlog("Marking company {$company->id} as large");
$company->account->companies()->update(['is_large' => true]); $company->account->companies()->update(['is_large' => true]);
@ -88,6 +105,22 @@ class CompanySizeCheck implements ShouldQueue
}); });
Account::where('plan', 'enterprise')
->whereDate('plan_expires', '>', now())
->whereHas('companies', function ($query){
$query->where('is_large',0);
})
->whereHas('company_users', function ($query){
$query->where('is_admin', 0);
})
->cursor()->each(function ($account){
$account->companies()->update(['is_large' => true]);
});
} }
} }
} }

View File

@ -131,7 +131,7 @@ class UpdateOrCreateProduct implements ShouldQueue
$product->company_id = $this->invoice->company_id; $product->company_id = $this->invoice->company_id;
$product->project_id = $this->invoice->project_id; $product->project_id = $this->invoice->project_id;
$product->vendor_id = $this->invoice->vendor_id; $product->vendor_id = $this->invoice->vendor_id;
$product->save(); $product->saveQuietly();
} }
} }

View File

@ -80,7 +80,11 @@ class ZipQuotes implements ShouldQueue
$path = $this->quotes->first()->client->quote_filepath($invitation); $path = $this->quotes->first()->client->quote_filepath($invitation);
$this->quotes->each(function ($quote) { $this->quotes->each(function ($quote) {
$quote->service()->createInvitations();
(new CreateEntityPdf($quote->invitations()->first()))->handle(); (new CreateEntityPdf($quote->invitations()->first()))->handle();
}); });
try { try {

View File

@ -79,7 +79,6 @@ class CreateUser
'is_locked' => 0, 'is_locked' => 0,
'permissions' => '', 'permissions' => '',
'notifications' => CompanySettings::notificationDefaults(), 'notifications' => CompanySettings::notificationDefaults(),
//'settings' => DefaultSettings::userSettings(),
'settings' => null, 'settings' => null,
]); ]);

View File

@ -99,6 +99,6 @@ class SystemLogger implements ShouldQueue
public function failed($e) public function failed($e)
{ {
nlog($e->getMessage()); config(['queue.failed.driver' => null]);
} }
} }

View File

@ -11,53 +11,34 @@
namespace App\Jobs\Util; namespace App\Jobs\Util;
use App\Jobs\Util\SystemLogger;
use App\Jobs\Util\WebhookSingle; use App\Jobs\Util\WebhookSingle;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Client as ClientModel; use App\Models\Company;
use App\Models\SystemLog;
use App\Models\Webhook; use App\Models\Webhook;
use App\Transformers\ArraySerializer;
use App\Utils\Ninja; use App\Utils\Ninja;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
class WebhookHandler implements ShouldQueue class WebhookHandler implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $entity;
private $event_id;
private $company;
public $tries = 1; //number of retries public $tries = 1; //number of retries
public $deleteWhenMissingModels = true; public $deleteWhenMissingModels = true;
private string $includes;
/** /**
* Create a new job instance. * Create a new job instance.
* *
* @param $event_id * @param $event_id
* @param $entity * @param $entity
*/ */
public function __construct($event_id, $entity, $company, $includes = '') public function __construct(private int $event_id, private $entity, private Company $company, private string $includes = ''){}
{
$this->event_id = $event_id;
$this->entity = $entity;
$this->company = $company;
$this->includes = $includes;
}
/** /**
* Execute the job. * Execute the job.
@ -74,12 +55,10 @@ class WebhookHandler implements ShouldQueue
return true; return true;
} }
$subscriptions = Webhook::where('company_id', $this->company->id) Webhook::where('company_id', $this->company->id)
->where('event_id', $this->event_id) ->where('event_id', $this->event_id)
->cursor() ->cursor()
->each(function ($subscription) { ->each(function ($subscription) {
// $this->process($subscription);
WebhookSingle::dispatch($subscription->id, $this->entity, $this->company->db, $this->includes); WebhookSingle::dispatch($subscription->id, $this->entity, $this->company->db, $this->includes);
@ -87,10 +66,8 @@ class WebhookHandler implements ShouldQueue
} }
public function failed($exception) public function failed($exception = null)
{ {
nlog(print_r($exception->getMessage(), 1));
} }
} }

View File

@ -15,11 +15,15 @@ use App\Jobs\Util\SystemLogger;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Client as ClientModel; use App\Models\Client as ClientModel;
use App\Models\Company; use App\Models\Company;
use App\Models\Product;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\Models\Vendor;
use App\Models\Webhook; use App\Models\Webhook;
use App\Transformers\ArraySerializer; use App\Transformers\ArraySerializer;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use GuzzleHttp\Exception\BadResponseException; use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\RequestOptions; use GuzzleHttp\RequestOptions;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -28,8 +32,6 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use League\Fractal\Manager; use League\Fractal\Manager;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
class WebhookSingle implements ShouldQueue class WebhookSingle implements ShouldQueue
{ {
@ -78,9 +80,15 @@ class WebhookSingle implements ShouldQueue
MultiDB::setDb($this->db); MultiDB::setDb($this->db);
$subscription = Webhook::with('company')->find($this->subscription_id); $subscription = Webhook::with('company')->find($this->subscription_id);
if($subscription)
nlog("firing event ID {$subscription->event_id}");
if(!$subscription){ if(!$subscription){
$this->fail(); $this->fail();
nlog("failed to fire event, could not find webhook ID {$this->subscription_id}");
return; return;
} }
@ -235,19 +243,27 @@ class WebhookSingle implements ShouldQueue
} }
private function resolveClient() private function resolveClient()
{ { nlog(get_class($this->entity));
//make sure it isn't an instance of the Client Model //make sure it isn't an instance of the Client Model
if ((! $this->entity instanceof ClientModel) && $this->entity->client()->exists()) { if (!$this->entity instanceof \App\Models\Client &&
return $this->entity->client; !$this->entity instanceof \App\Models\Vendor &&
} !$this->entity instanceof \App\Models\Product &&
!$this->entity instanceof \App\Models\PurchaseOrder &&
$this->entity->client()->exists()) {
return $this->company->clients()->first(); return $this->entity->client;
}
return null;
} }
public function failed($exception) public function failed($exception = null)
{ {
nlog(print_r($exception->getMessage(), 1)); config(['queue.failed.driver' => null]);
} }
} }

View File

@ -51,5 +51,6 @@ class RestoreClientActivity implements ShouldQueue
$fields->activity_type_id = Activity::RESTORE_CLIENT; $fields->activity_type_id = Activity::RESTORE_CLIENT;
$this->activity_repo->save($fields, $event->client, $event->event_vars); $this->activity_repo->save($fields, $event->client, $event->event_vars);
} }
} }

View File

@ -38,21 +38,18 @@ class CreateInvoicePdf implements ShouldQueue
if (isset($event->invoice)) { if (isset($event->invoice)) {
$event->invoice->invitations->each(function ($invitation) { $event->invoice->invitations->each(function ($invitation) {
// CreateEntityPdf::dispatch($invitation->load('invoice', 'contact.client.company'));
(new CreateEntityPdf($invitation->load('invoice', 'contact.client.company')))->handle(); (new CreateEntityPdf($invitation->load('invoice', 'contact.client.company')))->handle();
}); });
} }
if (isset($event->quote)) { if (isset($event->quote)) {
$event->quote->invitations->each(function ($invitation) { $event->quote->invitations->each(function ($invitation) {
// CreateEntityPdf::dispatch($invitation->load('quote', 'contact.client.company'));
(new CreateEntityPdf($invitation->load('quote', 'contact.client.company')))->handle(); (new CreateEntityPdf($invitation->load('quote', 'contact.client.company')))->handle();
}); });
} }
if (isset($event->credit)) { if (isset($event->credit)) {
$event->credit->invitations->each(function ($invitation) { $event->credit->invitations->each(function ($invitation) {
// CreateEntityPdf::dispatch($invitation->load('credit', 'contact.client.company'));
(new CreateEntityPdf($invitation->load('credit', 'contact.client.company')))->handle(); (new CreateEntityPdf($invitation->load('credit', 'contact.client.company')))->handle();
}); });

View File

@ -13,6 +13,8 @@ namespace App\Listeners\Subscription;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Models\Account; use App\Models\Account;
use App\Models\Company;
use App\Notifications\Ninja\RenewalFailureNotification;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Imdhemy\Purchases\Events\AppStore\DidRenew; use Imdhemy\Purchases\Events\AppStore\DidRenew;
@ -38,10 +40,18 @@ class AppStoreRenewSubscription implements ShouldQueue
$inapp_transaction_id = $event->getSubscriptionId(); //$subscription_id $inapp_transaction_id = $event->getSubscriptionId(); //$subscription_id
nlog("inapp upgrade processing for = {$inapp_transaction_id}");
MultiDB::findAndSetDbByInappTransactionId($inapp_transaction_id); MultiDB::findAndSetDbByInappTransactionId($inapp_transaction_id);
$account = Account::where('inapp_transaction_id', $inapp_transaction_id)->first(); $account = Account::where('inapp_transaction_id', $inapp_transaction_id)->first();
if(!$account) {
$ninja_company = Company::on('db-ninja-01')->find(config('ninja.ninja_default_company_id'));
$ninja_company->notification(new RenewalFailureNotification("{$inapp_transaction_id}"))->ninja();
return;
}
if($account->plan_term == 'month') if($account->plan_term == 'month')
$account->plan_expires = now()->addMonth(); $account->plan_expires = now()->addMonth();
elseif($account->plan_term == 'year') elseif($account->plan_term == 'year')

View File

@ -27,6 +27,8 @@ class BaseEmailEngine implements EngineInterface
public $attachments = []; public $attachments = [];
public $attachment_links = [];
public $link; public $link;
public $text; public $text;
@ -37,6 +39,8 @@ class BaseEmailEngine implements EngineInterface
public $text_footer; public $text_footer;
public int $max_attachment_size = 3000000;
public function setFooter($footer) public function setFooter($footer)
{ {
$this->footer = $footer; $this->footer = $footer;
@ -95,6 +99,14 @@ class BaseEmailEngine implements EngineInterface
return $this; return $this;
} }
public function setAttachmentLinks($links)
{
$this->attachment_links = array_merge($this->getAttachmentLinks(), $links);
return $this;
}
public function setViewLink($link) public function setViewLink($link)
{ {
$this->link = $link; $this->link = $link;
@ -131,6 +143,11 @@ class BaseEmailEngine implements EngineInterface
return $this->attachments; return $this->attachments;
} }
public function getAttachmentLinks()
{
return $this->attachment_links;
}
public function getFooter() public function getFooter()
{ {
return $this->footer; return $this->footer;

View File

@ -18,6 +18,7 @@ use App\Utils\Ninja;
use App\Utils\Number; use App\Utils\Number;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang; use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class CreditEmailEngine extends BaseEmailEngine class CreditEmailEngine extends BaseEmailEngine
{ {
@ -136,11 +137,19 @@ class CreditEmailEngine extends BaseEmailEngine
// Storage::url // Storage::url
foreach ($this->credit->documents as $document) { foreach ($this->credit->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
} }
foreach ($this->credit->company->documents as $document) { foreach ($this->credit->company->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
} }
} }

View File

@ -23,6 +23,7 @@ use App\Utils\Number;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang; use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class InvoiceEmailEngine extends BaseEmailEngine class InvoiceEmailEngine extends BaseEmailEngine
{ {
@ -136,13 +137,22 @@ class InvoiceEmailEngine extends BaseEmailEngine
//attach third party documents //attach third party documents
if ($this->client->getSetting('document_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) { if ($this->client->getSetting('document_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
// Storage::url // Storage::url
foreach ($this->invoice->documents as $document) { foreach ($this->invoice->documents as $document) {
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
} }
foreach ($this->invoice->company->documents as $document) { foreach ($this->invoice->company->documents as $document) {
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
} }
$line_items = $this->invoice->line_items; $line_items = $this->invoice->line_items;
@ -160,7 +170,12 @@ class InvoiceEmailEngine extends BaseEmailEngine
->cursor() ->cursor()
->each(function ($expense) { ->each(function ($expense) {
foreach ($expense->documents as $document) { foreach ($expense->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
} }
}); });
} }
@ -176,7 +191,12 @@ class InvoiceEmailEngine extends BaseEmailEngine
->cursor() ->cursor()
->each(function ($task) { ->each(function ($task) {
foreach ($task->documents as $document) { foreach ($task->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
} }
}); });
} }

View File

@ -19,6 +19,7 @@ use App\Utils\Ninja;
use App\Utils\Number; use App\Utils\Number;
use App\Utils\Traits\MakesDates; use App\Utils\Traits\MakesDates;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;
class PaymentEmailEngine extends BaseEmailEngine class PaymentEmailEngine extends BaseEmailEngine
{ {
@ -100,7 +101,11 @@ class PaymentEmailEngine extends BaseEmailEngine
if ($this->client->getSetting('document_email_attachment') !== false) if ($this->client->getSetting('document_email_attachment') !== false)
{ {
foreach ($invoice->documents as $document) { foreach ($invoice->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
} }
} }

View File

@ -27,6 +27,7 @@ use App\Utils\Traits\MakesHash;
use App\Utils\VendorHtmlEngine; use App\Utils\VendorHtmlEngine;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang; use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class PurchaseOrderEmailEngine extends BaseEmailEngine class PurchaseOrderEmailEngine extends BaseEmailEngine
{ {
@ -126,11 +127,6 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine
->setTextBody($text_body); ->setTextBody($text_body);
if ($this->vendor->getSetting('pdf_email_attachment') !== false && $this->purchase_order->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { if ($this->vendor->getSetting('pdf_email_attachment') !== false && $this->purchase_order->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
// if (Ninja::isHosted()) {
// $this->setAttachments([$this->purchase_order->pdf_file_path($this->invitation, 'url', true)]);
// } else {
// $this->setAttachments([$this->purchase_order->pdf_file_path($this->invitation)]);
// }
$pdf = (new CreatePurchaseOrderPdf($this->invitation))->rawPdf(); $pdf = (new CreatePurchaseOrderPdf($this->invitation))->rawPdf();
@ -143,13 +139,19 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine
// Storage::url // Storage::url
foreach ($this->purchase_order->documents as $document) { foreach ($this->purchase_order->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
// $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]); if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
} }
foreach ($this->purchase_order->company->documents as $document) { foreach ($this->purchase_order->company->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
// $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]); if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
} }
} }

View File

@ -18,6 +18,7 @@ use App\Utils\Ninja;
use App\Utils\Number; use App\Utils\Number;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang; use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class QuoteEmailEngine extends BaseEmailEngine class QuoteEmailEngine extends BaseEmailEngine
{ {
@ -128,11 +129,19 @@ class QuoteEmailEngine extends BaseEmailEngine
// Storage::url // Storage::url
foreach ($this->quote->documents as $document) { foreach ($this->quote->documents as $document) {
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
} }
foreach ($this->quote->company->documents as $document) { foreach ($this->quote->company->documents as $document) {
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
if($document->size > $this->max_attachment_size)
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
else
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
} }
} }

View File

@ -116,6 +116,7 @@ class TemplateEmail extends Mailable
'company' => $company, 'company' => $company,
'whitelabel' => $this->client->user->account->isPaid() ? true : false, 'whitelabel' => $this->client->user->account->isPaid() ? true : false,
'logo' => $this->company->present()->logo($settings), 'logo' => $this->company->present()->logo($settings),
'links' => $this->build_email->getAttachmentLinks(),
]); ]);
foreach ($this->build_email->getAttachments() as $file) { foreach ($this->build_email->getAttachments() as $file) {

View File

@ -109,6 +109,7 @@ class VendorTemplateEmail extends Mailable
'company' => $this->company, 'company' => $this->company,
'whitelabel' => $this->vendor->user->account->isPaid() ? true : false, 'whitelabel' => $this->vendor->user->account->isPaid() ? true : false,
'logo' => $this->company->present()->logo($settings), 'logo' => $this->company->present()->logo($settings),
'links' => $this->build_email->getAttachmentLinks(),
]); ]);

View File

@ -375,18 +375,4 @@ class Activity extends StaticModel
return $this->belongsTo(Company::class); return $this->belongsTo(Company::class);
} }
// /**
// * @return mixed
// */
// public function resolveRouteBinding($value, $field = null)
// {
// if (is_numeric($value)) {
// throw new ModelNotFoundException("Record with value {$value} not found");
// }
// return $this
// //->withTrashed()
// ->where('id', $this->decodePrimaryKey($value))->firstOrFail();
// }
} }

View File

@ -69,17 +69,5 @@ class ClientGatewayToken extends BaseModel
{ {
return $this->belongsTo(User::class)->withTrashed(); return $this->belongsTo(User::class)->withTrashed();
} }
// /**
// * Retrieve the model for a bound value.
// *
// * @param mixed $value
// * @param null $field
// * @return Model|null
// */
// public function resolveRouteBinding($value, $field = null)
// {
// return $this
// ->where('id', $this->decodePrimaryKey($value))->firstOrFail();
// }
} }

View File

@ -43,6 +43,10 @@ class CompanyGateway extends BaseModel
'require_client_phone', 'require_client_phone',
'require_contact_name', 'require_contact_name',
'require_contact_email', 'require_contact_email',
'require_custom_value1',
'require_custom_value2',
'require_custom_value3',
'require_custom_value4',
'update_details', 'update_details',
'config', 'config',
'fees_and_limits', 'fees_and_limits',
@ -412,12 +416,4 @@ class CompanyGateway extends BaseModel
return route('payment_webhook', ['company_key' => $this->company->company_key, 'company_gateway_id' => $this->hashed_id]); return route('payment_webhook', ['company_key' => $this->company->company_key, 'company_gateway_id' => $this->hashed_id]);
} }
// public function resolveRouteBinding($value, $field = null)
// {
// return $this
// ->where('id', $this->decodePrimaryKey($value))->withTrashed()->firstOrFail();
// }
} }

View File

@ -249,18 +249,18 @@ class Credit extends BaseModel
if ($this->balance == 0) { if ($this->balance == 0) {
$this->status_id = self::STATUS_APPLIED; $this->status_id = self::STATUS_APPLIED;
$this->save(); $this->saveQuietly();
return; return;
} }
$this->save(); $this->saveQuietly();
} }
public function setStatus($status) public function setStatus($status)
{ {
$this->status_id = $status; $this->status_id = $status;
$this->save(); $this->saveQuietly();
} }
public function pdf_file_path($invitation = null, string $type = 'path', bool $portal = false) public function pdf_file_path($invitation = null, string $type = 'path', bool $portal = false)
@ -313,7 +313,7 @@ class Credit extends BaseModel
$this->invitations->each(function ($invitation) { $this->invitations->each(function ($invitation) {
if (! isset($invitation->sent_date)) { if (! isset($invitation->sent_date)) {
$invitation->sent_date = Carbon::now(); $invitation->sent_date = Carbon::now();
$invitation->save(); $invitation->saveQuietly();
} }
}); });
} }

View File

@ -23,7 +23,6 @@ class Currency extends StaticModel
'updated_at' => 'timestamp', 'updated_at' => 'timestamp',
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'deleted_at' => 'timestamp', 'deleted_at' => 'timestamp',
//'precision' => 'string',
'precision' => 'integer', 'precision' => 'integer',
]; ];
} }

View File

@ -14,14 +14,13 @@ namespace App\Models;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
class GroupSetting extends StaticModel class GroupSetting extends StaticModel
{ {
use MakesHash; use MakesHash;
use SoftDeletes; use SoftDeletes;
//public $timestamps = false;
protected $casts = [ protected $casts = [
'settings' => 'object', 'settings' => 'object',
'updated_at' => 'timestamp', 'updated_at' => 'timestamp',
@ -65,4 +64,25 @@ class GroupSetting extends StaticModel
return $this->morphMany(Document::class, 'documentable'); return $this->morphMany(Document::class, 'documentable');
} }
/**
* Retrieve the model for a bound value.
*
* @param mixed $value
* @param null $field
* @return Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
if (is_numeric($value)) {
throw new ModelNotFoundException("Record with value {$value} not found");
}
return $this
->withTrashed()
->company()
->where('id', $this->decodePrimaryKey($value))->firstOrFail();
}
} }

View File

@ -292,14 +292,6 @@ class Payment extends BaseModel
return new PaymentService($this); return new PaymentService($this);
} }
// public function resolveRouteBinding($value, $field = null)
// {
// return $this
// ->withTrashed()
// ->where('id', $this->decodePrimaryKey($value))->firstOrFail();
// }
public function refund(array $data) :self public function refund(array $data) :self
{ {
return $this->service()->refundPayment($data); return $this->service()->refundPayment($data);

View File

@ -141,6 +141,10 @@ class PurchaseOrder extends BaseModel
} }
} }
public function getEntityType()
{
return self::class;
}
public function assigned_user() public function assigned_user()
{ {
@ -186,7 +190,7 @@ class PurchaseOrder extends BaseModel
$this->invitations->each(function ($invitation) { $this->invitations->each(function ($invitation) {
if (! isset($invitation->sent_date)) { if (! isset($invitation->sent_date)) {
$invitation->sent_date = Carbon::now(); $invitation->sent_date = Carbon::now();
$invitation->save(); $invitation->saveQuietly();
} }
}); });
} }

View File

@ -212,7 +212,7 @@ class Quote extends BaseModel
$this->invitations->each(function ($invitation) { $this->invitations->each(function ($invitation) {
if (! isset($invitation->sent_date)) { if (! isset($invitation->sent_date)) {
$invitation->sent_date = Carbon::now(); $invitation->sent_date = Carbon::now();
$invitation->save(); $invitation->saveQuietly();
} }
}); });
} }

View File

@ -57,8 +57,7 @@ class StaticModel extends Model
} }
return $this return $this
->withTrashed()
->company()
->where('id', $this->decodePrimaryKey($value))->firstOrFail(); ->where('id', $this->decodePrimaryKey($value))->firstOrFail();
} }
} }

View File

@ -367,22 +367,41 @@ class User extends Authenticatable implements MustVerifyEmail
*/ */
public function hasPermission($permission) : bool public function hasPermission($permission) : bool
{ {
$parts = explode('_', $permission);
$all_permission = '____';
/**
* We use the limit parameter here to ensure we don't split on permissions that have multiple underscores.
*
* For example view_recurring_invoice without the limit would split to view bank recurring invoice
*
* Using only part 0 and 1 would search for permission view_recurring / edit_recurring so this would
* leak permissions for other recurring_* entities
*
* The solution here will split the word - consistently - into view _ {entity} and edit _ {entity}
*
*/
$parts = explode('_', $permission, 2);
$all_permission = '____';
$edit_all = '____';
$edit_entity = '____';
/* If we have multiple parts, then make sure we search for the _all permission */
if (count($parts) > 1) { if (count($parts) > 1) {
$all_permission = $parts[0].'_all'; $all_permission = $parts[0].'_all';
/*If this is a view search, make sure we add in the edit_{entity} AND edit_all permission into the checks*/
if($parts[0] == 'view') {
$edit_all = 'edit_all';
$edit_entity = "edit_{$parts[1]}";
}
} }
return $this->isOwner() || return $this->isOwner() ||
$this->isAdmin() || $this->isAdmin() ||
(stripos($this->token()->cu->permissions, $permission) !== false) ||
(stripos($this->token()->cu->permissions, $all_permission) !== false) || (stripos($this->token()->cu->permissions, $all_permission) !== false) ||
(stripos($this->token()->cu->permissions, $permission) !== false); (stripos($this->token()->cu->permissions, $edit_all) !== false) ||
(stripos($this->token()->cu->permissions, $edit_entity) !== false);
// return $this->isOwner() ||
// $this->isAdmin() ||
// (is_int(stripos($this->token()->cu->permissions, $all_permission))) ||
// (is_int(stripos($this->token()->cu->permissions, $permission)));
} }

View File

@ -145,7 +145,7 @@ class VendorContact extends Authenticatable implements HasLocalePreference
{ {
return $this return $this
->withTrashed() ->withTrashed()
->company() // ->company()
->where('id', $this->decodePrimaryKey($value)) ->where('id', $this->decodePrimaryKey($value))
->firstOrFail(); ->firstOrFail();
} }

View File

@ -18,47 +18,47 @@ class Webhook extends BaseModel
use SoftDeletes; use SoftDeletes;
use Filterable; use Filterable;
const EVENT_CREATE_CLIENT = 1; const EVENT_CREATE_CLIENT = 1; //tested
const EVENT_CREATE_INVOICE = 2; const EVENT_CREATE_INVOICE = 2; //tested
const EVENT_CREATE_QUOTE = 3; const EVENT_CREATE_QUOTE = 3; //tested
const EVENT_CREATE_PAYMENT = 4; const EVENT_CREATE_PAYMENT = 4; //tested
const EVENT_CREATE_VENDOR = 5; const EVENT_CREATE_VENDOR = 5; //tested
const EVENT_UPDATE_QUOTE = 6; const EVENT_UPDATE_QUOTE = 6; //tested
const EVENT_DELETE_QUOTE = 7; const EVENT_DELETE_QUOTE = 7; //tested
const EVENT_UPDATE_INVOICE = 8; const EVENT_UPDATE_INVOICE = 8; //tested
const EVENT_DELETE_INVOICE = 9; const EVENT_DELETE_INVOICE = 9; //tested
const EVENT_UPDATE_CLIENT = 10; const EVENT_UPDATE_CLIENT = 10; //tested
const EVENT_DELETE_CLIENT = 11; const EVENT_DELETE_CLIENT = 11; //tested
const EVENT_DELETE_PAYMENT = 12; const EVENT_DELETE_PAYMENT = 12; //tested
const EVENT_UPDATE_VENDOR = 13; const EVENT_UPDATE_VENDOR = 13; //tested
const EVENT_DELETE_VENDOR = 14; const EVENT_DELETE_VENDOR = 14; //tested
const EVENT_CREATE_EXPENSE = 15; const EVENT_CREATE_EXPENSE = 15; //tested
const EVENT_UPDATE_EXPENSE = 16; const EVENT_UPDATE_EXPENSE = 16; //tested
const EVENT_DELETE_EXPENSE = 17; const EVENT_DELETE_EXPENSE = 17; //tested
const EVENT_CREATE_TASK = 18; const EVENT_CREATE_TASK = 18; //tested
const EVENT_UPDATE_TASK = 19; const EVENT_UPDATE_TASK = 19; //tested
const EVENT_DELETE_TASK = 20; const EVENT_DELETE_TASK = 20; //tested
const EVENT_APPROVE_QUOTE = 21; const EVENT_APPROVE_QUOTE = 21; //tested
const EVENT_LATE_INVOICE = 22; const EVENT_LATE_INVOICE = 22;
@ -66,22 +66,86 @@ class Webhook extends BaseModel
const EVENT_REMIND_INVOICE = 24; const EVENT_REMIND_INVOICE = 24;
const EVENT_PROJECT_CREATE = 25; const EVENT_PROJECT_CREATE = 25; //tested
const EVENT_PROJECT_UPDATE = 26; const EVENT_PROJECT_UPDATE = 26; //tested
const EVENT_CREATE_CREDIT = 27; const EVENT_CREATE_CREDIT = 27; //tested
const EVENT_UPDATE_CREDIT = 28; const EVENT_UPDATE_CREDIT = 28; //tested
const EVENT_DELETE_CREDIT = 29; const EVENT_DELETE_CREDIT = 29; //tested
const EVENT_PROJECT_DELETE = 30; const EVENT_PROJECT_DELETE = 30; //tested
const EVENT_UPDATE_PAYMENT = 31; const EVENT_UPDATE_PAYMENT = 31; //tested
const EVENT_ARCHIVE_PAYMENT = 32; //tested
const EVENT_ARCHIVE_INVOICE = 33; //tested
const EVENT_ARCHIVE_QUOTE = 34; //tested
const EVENT_ARCHIVE_CREDIT = 35; //tested
const EVENT_ARCHIVE_TASK = 36; //tested
const EVENT_ARCHIVE_CLIENT = 37; //tested
const EVENT_ARCHIVE_PROJECT = 38; //tested
const EVENT_ARCHIVE_EXPENSE = 39; //tested
const EVENT_RESTORE_PAYMENT = 40; //tested
const EVENT_RESTORE_INVOICE = 41; //tested
const EVENT_RESTORE_QUOTE = 42; ///tested
const EVENT_RESTORE_CREDIT = 43; //tested
const EVENT_RESTORE_TASK = 44; //tested
const EVENT_RESTORE_CLIENT = 45; //tested
const EVENT_RESTORE_PROJECT = 46; //tested
const EVENT_RESTORE_EXPENSE = 47; //tested
const EVENT_ARCHIVE_VENDOR = 48; //tested
const EVENT_RESTORE_VENDOR = 49; //tested
const EVENT_CREATE_PRODUCT = 50; //tested
const EVENT_UPDATE_PRODUCT = 51; //tested
const EVENT_DELETE_PRODUCT = 52; //tested
const EVENT_RESTORE_PRODUCT = 53; //tested
const EVENT_ARCHIVE_PRODUCT = 54; //tested
const EVENT_CREATE_PURCHASE_ORDER = 55; //tested
const EVENT_UPDATE_PURCHASE_ORDER = 56; //tested
const EVENT_DELETE_PURCHASE_ORDER = 57; //tested
const EVENT_RESTORE_PURCHASE_ORDER = 58; //tested
const EVENT_ARCHIVE_PURCHASE_ORDER = 59; //tested
public static $valid_events = [ public static $valid_events = [
self::EVENT_CREATE_PURCHASE_ORDER,
self::EVENT_UPDATE_PURCHASE_ORDER,
self::EVENT_DELETE_PURCHASE_ORDER,
self::EVENT_RESTORE_PURCHASE_ORDER,
self::EVENT_ARCHIVE_PURCHASE_ORDER,
self::EVENT_UPDATE_PRODUCT,
self::EVENT_DELETE_PRODUCT,
self::EVENT_RESTORE_PRODUCT,
self::EVENT_ARCHIVE_PRODUCT,
self::EVENT_CREATE_CLIENT, self::EVENT_CREATE_CLIENT,
self::EVENT_CREATE_INVOICE, self::EVENT_CREATE_INVOICE,
self::EVENT_CREATE_QUOTE, self::EVENT_CREATE_QUOTE,
@ -112,7 +176,26 @@ class Webhook extends BaseModel
self::EVENT_UPDATE_CREDIT, self::EVENT_UPDATE_CREDIT,
self::EVENT_DELETE_CREDIT, self::EVENT_DELETE_CREDIT,
self::EVENT_PROJECT_DELETE, self::EVENT_PROJECT_DELETE,
self::EVENT_UPDATE_PAYMENT self::EVENT_UPDATE_PAYMENT,
self::EVENT_ARCHIVE_EXPENSE,
self::EVENT_ARCHIVE_PROJECT,
self::EVENT_ARCHIVE_CLIENT,
self::EVENT_ARCHIVE_TASK,
self::EVENT_ARCHIVE_CREDIT,
self::EVENT_ARCHIVE_QUOTE,
self::EVENT_ARCHIVE_INVOICE,
self::EVENT_ARCHIVE_PAYMENT,
self::EVENT_ARCHIVE_VENDOR,
self::EVENT_RESTORE_EXPENSE,
self::EVENT_RESTORE_PROJECT,
self::EVENT_RESTORE_CLIENT,
self::EVENT_RESTORE_TASK,
self::EVENT_RESTORE_CREDIT,
self::EVENT_RESTORE_QUOTE,
self::EVENT_RESTORE_INVOICE,
self::EVENT_RESTORE_PAYMENT,
self::EVENT_RESTORE_VENDOR
]; ];
protected $fillable = [ protected $fillable = [

View File

@ -30,13 +30,7 @@ class ClientAccountNotFound extends Notification
* @return void * @return void
*/ */
public function __construct(protected string $account_key, protected string $email){}
protected string $account_key;
public function __construct(string $account_key)
{
$this->account_key = $account_key;
}
/** /**
* Get the notification's delivery channels. * Get the notification's delivery channels.
@ -77,6 +71,7 @@ class ClientAccountNotFound extends Notification
$content = "Client not found, unable to remove account\n"; $content = "Client not found, unable to remove account\n";
$content .= "Account: {$this->account_key }\n"; $content .= "Account: {$this->account_key }\n";
$content .= "Email: {$this->email}\n";
return (new SlackMessage) return (new SlackMessage)
->success() ->success()

View File

@ -68,7 +68,7 @@ class RenewalFailureNotification extends Notification
public function toSlack($notifiable) public function toSlack($notifiable)
{ {
$content = "Plan paid, account not updated\n"; $content = "Plan paid, account not updated\n";
$content .= "Contact: {$this->notification_message}"; $content .= "Contact/Inapp Purchase: {$this->notification_message}";
return (new SlackMessage) return (new SlackMessage)
->success() ->success()

View File

@ -12,6 +12,7 @@
namespace App\Observers; namespace App\Observers;
use App\Models\ClientContact; use App\Models\ClientContact;
use App\Models\CreditInvitation;
use App\Models\InvoiceInvitation; use App\Models\InvoiceInvitation;
use App\Models\QuoteInvitation; use App\Models\QuoteInvitation;
use App\Models\RecurringInvoiceInvitation; use App\Models\RecurringInvoiceInvitation;
@ -79,7 +80,12 @@ class ClientContactObserver
}); });
CreditInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite){
if($invite->credits()->doesnthave('invitations'))
$invite->credit->service()->createInvitations();
});
} }
/** /**
@ -90,9 +96,6 @@ class ClientContactObserver
*/ */
public function restored(ClientContact $clientContact) public function restored(ClientContact $clientContact)
{ {
// $clientContact->invoice_invitations()->restore();
// $clientContact->quote_invitations()->restore();
// $clientContact->credit_invitations()->restore();
} }
/** /**

View File

@ -17,6 +17,8 @@ use App\Models\Webhook;
class ClientObserver class ClientObserver
{ {
public $afterCommit = true;
/** /**
* Handle the client "created" event. * Handle the client "created" event.
* *
@ -25,13 +27,13 @@ class ClientObserver
*/ */
public function created(Client $client) public function created(Client $client)
{ {
$subscriptions = Webhook::where('company_id', $client->company->id) $subscriptions = Webhook::where('company_id', $client->company_id)
->where('event_id', Webhook::EVENT_CREATE_CLIENT) ->where('event_id', Webhook::EVENT_CREATE_CLIENT)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_CREATE_CLIENT, $client, $client->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch(Webhook::EVENT_CREATE_CLIENT, $client, $client->company)->delay(0);
}
} }
/** /**
@ -42,51 +44,44 @@ class ClientObserver
*/ */
public function updated(Client $client) public function updated(Client $client)
{ {
$subscriptions = Webhook::where('company_id', $client->company->id)
->where('event_id', Webhook::EVENT_UPDATE_CLIENT) $event = Webhook::EVENT_UPDATE_CLIENT;
if($client->getOriginal('deleted_at') && !$client->deleted_at)
$event = Webhook::EVENT_RESTORE_CLIENT;
if($client->is_deleted)
$event = Webhook::EVENT_DELETE_CLIENT;
$subscriptions = Webhook::where('company_id', $client->company_id)
->where('event_id', $event)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_UPDATE_CLIENT, $client, $client->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch($event, $client, $client->company)->delay(0);
}
} }
/** /**
* Handle the client "deleted" event. * Handle the client "archived" event.
* *
* @param Client $client * @param Client $client
* @return void * @return void
*/ */
public function deleted(Client $client) public function deleted(Client $client)
{ {
$subscriptions = Webhook::where('company_id', $client->company->id) if($client->is_deleted)
->where('event_id', Webhook::EVENT_DELETE_CLIENT) return;
$subscriptions = Webhook::where('company_id', $client->company_id)
->where('event_id', Webhook::EVENT_ARCHIVE_CLIENT)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_DELETE_CLIENT, $client, $client->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch(Webhook::EVENT_ARCHIVE_CLIENT, $client, $client->company)->delay(0);
}
} }
/**
* Handle the client "restored" event.
*
* @param Client $client
* @return void
*/
public function restored(Client $client)
{
//
}
/**
* Handle the client "force deleted" event.
*
* @param Client $client
* @return void
*/
public function forceDeleted(Client $client)
{
//
}
} }

View File

@ -19,6 +19,9 @@ use App\Models\Webhook;
class CreditObserver class CreditObserver
{ {
public $afterCommit = true;
/** /**
* Handle the client "created" event. * Handle the client "created" event.
* *
@ -27,12 +30,12 @@ class CreditObserver
*/ */
public function created(Credit $credit) public function created(Credit $credit)
{ {
$subscriptions = Webhook::where('company_id', $credit->company->id) $subscriptions = Webhook::where('company_id', $credit->company_id)
->where('event_id', Webhook::EVENT_CREATE_CREDIT) ->where('event_id', Webhook::EVENT_CREATE_CREDIT)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_CREATE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch(Webhook::EVENT_CREATE_CREDIT, $credit, $credit->company)->delay(0);
} }
} }
@ -44,13 +47,21 @@ class CreditObserver
*/ */
public function updated(Credit $credit) public function updated(Credit $credit)
{ {
$subscriptions = Webhook::where('company_id', $credit->company->id) $event = Webhook::EVENT_UPDATE_CREDIT;
->where('event_id', Webhook::EVENT_UPDATE_CREDIT)
if($credit->getOriginal('deleted_at') && !$credit->deleted_at)
$event = Webhook::EVENT_RESTORE_CREDIT;
if($credit->is_deleted)
$event = Webhook::EVENT_DELETE_CREDIT;
$subscriptions = Webhook::where('company_id', $credit->company_id)
->where('event_id', $event)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_UPDATE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch($event, $credit, $credit->company)->delay(0);
}
} }
/** /**
@ -61,13 +72,16 @@ class CreditObserver
*/ */
public function deleted(Credit $credit) public function deleted(Credit $credit)
{ {
$subscriptions = Webhook::where('company_id', $credit->company->id) if($credit->is_deleted)
->where('event_id', Webhook::EVENT_DELETE_CREDIT) return;
$subscriptions = Webhook::where('company_id', $credit->company_id)
->where('event_id', Webhook::EVENT_ARCHIVE_CREDIT)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_DELETE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch(Webhook::EVENT_ARCHIVE_CREDIT, $credit, $credit->company)->delay(0);
}
} }
/** /**
@ -91,4 +105,10 @@ class CreditObserver
{ {
// //
} }
/**
* Handle the client "archive" event.
*
* @param Credit $credit
* @return void
*/
} }

View File

@ -17,6 +17,8 @@ use App\Models\Webhook;
class ExpenseObserver class ExpenseObserver
{ {
public $afterCommit = true;
/** /**
* Handle the expense "created" event. * Handle the expense "created" event.
* *
@ -25,13 +27,13 @@ class ExpenseObserver
*/ */
public function created(Expense $expense) public function created(Expense $expense)
{ {
$subscriptions = Webhook::where('company_id', $expense->company->id) $subscriptions = Webhook::where('company_id', $expense->company_id)
->where('event_id', Webhook::EVENT_CREATE_EXPENSE) ->where('event_id', Webhook::EVENT_CREATE_EXPENSE)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_CREATE_EXPENSE, $expense, $expense->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch(Webhook::EVENT_CREATE_EXPENSE, $expense, $expense->company)->delay(0);
}
} }
/** /**
@ -42,13 +44,22 @@ class ExpenseObserver
*/ */
public function updated(Expense $expense) public function updated(Expense $expense)
{ {
$subscriptions = Webhook::where('company_id', $expense->company->id) $event = Webhook::EVENT_UPDATE_EXPENSE;
->where('event_id', Webhook::EVENT_UPDATE_EXPENSE)
->exists();
if ($subscriptions) { if($expense->getOriginal('deleted_at') && !$expense->deleted_at)
WebhookHandler::dispatch(Webhook::EVENT_UPDATE_EXPENSE, $expense, $expense->company)->delay(now()->addSeconds(2)); $event = Webhook::EVENT_RESTORE_EXPENSE;
}
if($expense->is_deleted)
$event = Webhook::EVENT_DELETE_EXPENSE;
$subscriptions = Webhook::where('company_id', $expense->company_id)
->where('event_id', $event)
->exists();
if ($subscriptions)
WebhookHandler::dispatch($event, $expense, $expense->company)->delay(0);
} }
/** /**
@ -59,13 +70,16 @@ class ExpenseObserver
*/ */
public function deleted(Expense $expense) public function deleted(Expense $expense)
{ {
$subscriptions = Webhook::where('company_id', $expense->company->id) if($expense->is_deleted)
->where('event_id', Webhook::EVENT_DELETE_EXPENSE) return;
$subscriptions = Webhook::where('company_id', $expense->company_id)
->where('event_id', Webhook::EVENT_ARCHIVE_EXPENSE)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_DELETE_EXPENSE, $expense, $expense->company)->delay(now()->addSeconds(2)); WebhookHandler::dispatch(Webhook::EVENT_ARCHIVE_EXPENSE, $expense, $expense->company)->delay(0);
}
} }
/** /**
@ -89,4 +103,10 @@ class ExpenseObserver
{ {
// //
} }
/**
* Handle the expense "archive" event.
*
* @param Expense $expense
* @return void
*/
} }

Some files were not shown because too many files have changed in this diff Show More