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()

View File

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

View File

@ -33,7 +33,6 @@ use PDOException;
use Sentry\Laravel\Integration;
use Sentry\State\Scope;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use League\Flysystem\UnableToCreateDirectory;
@ -222,7 +221,7 @@ class Handler extends ExceptionHandler
return response()->json(['message'=>'Too many requests'], 429);
// } elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
// 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);
} elseif ($exception instanceof TokenMismatchException) {
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
{
if(strlen($name) >=1)
return $this->builder->where('bank_account_name', 'like', '%'.$name.'%');
if (strlen($name) == 0) {
return $this->builder;
}
return $this->builder;
return $this->builder->where('bank_account_name', 'like', '%'.$name.'%');
}
/**
@ -90,10 +91,14 @@ class BankIntegrationFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

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

View File

@ -11,11 +11,7 @@
namespace App\Filters;
use App\Models\BankTransactionRule;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
/**
* BankTransactionRuleilters.
@ -30,10 +26,11 @@ class BankTransactionRuleFilters extends QueryFilters
*/
public function name(string $name = ''): Builder
{
if(strlen($name) >=1)
return $this->builder->where('name', 'like', '%'.$name.'%');
if (strlen($name) == 0) {
return $this->builder;
}
return $this->builder;
return $this->builder->where('name', 'like', '%'.$name.'%');
}
/**
@ -43,7 +40,7 @@ class BankTransactionRuleFilters extends QueryFilters
* @return Builder
* @deprecated
*/
public function filter(string $filter = '') : Builder
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
@ -61,26 +58,17 @@ class BankTransactionRuleFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort) : Builder
public function sort(string $sort = ''): Builder
{
$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]);
}
/**
* 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.
*

View File

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

View File

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

View File

@ -30,7 +30,7 @@ class CreditFilters extends QueryFilters
* @param string credit_status The credit status as seen by the client
* @return Builder
*/
public function credit_status(string $value = '') :Builder
public function credit_status(string $value = ''): Builder
{
if (strlen($value) == 0) {
return $this->builder;
@ -66,7 +66,7 @@ class CreditFilters extends QueryFilters
* @return Builder
* @deprecated
*/
public function filter(string $filter = '') : Builder
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
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.
*
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort) : Builder
public function sort(string $sort = ''): Builder
{
$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]);
}
@ -123,7 +136,7 @@ class CreditFilters extends QueryFilters
*
* @return Builder
*/
private function contactViewFilter() : Builder
private function contactViewFilter(): Builder
{
return $this->builder
->whereCompanyId(auth()->guard('contact')->user()->company->id)

View File

@ -32,7 +32,7 @@ class DesignFilters extends QueryFilters
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.'%');
});
}
@ -44,14 +44,15 @@ class DesignFilters extends QueryFilters
*
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$sort_col = explode('|', $sort);
if(is_array($sort_col))
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
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]);
}
/**
@ -61,7 +62,6 @@ class DesignFilters extends QueryFilters
*/
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');
}
}

View File

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

View File

@ -25,7 +25,7 @@ class ExpenseCategoryFilters extends QueryFilters
* @return Builder
* @deprecated
*/
public function filter(string $filter = '') : Builder
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
@ -41,10 +41,14 @@ class ExpenseCategoryFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort) : Builder
public function sort(string $sort = ''): Builder
{
$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']))
return $this->builder->orderBy($sort_col[0], $sort_col[1]);

View File

@ -25,7 +25,7 @@ class ExpenseFilters extends QueryFilters
* @return Builder
* @deprecated
*/
public function filter(string $filter = '') : Builder
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
@ -53,7 +53,7 @@ class ExpenseFilters extends QueryFilters
*
* @return Builder
*/
public function client_status(string $value = '') :Builder
public function client_status(string $value = ''): Builder
{
if (strlen($value) == 0) {
return $this->builder;
@ -132,16 +132,29 @@ class ExpenseFilters extends QueryFilters
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.
*
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort) : Builder
public function sort(string $sort = ''): Builder
{
$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'])) {
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
}

View File

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

View File

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

View File

@ -42,10 +42,14 @@ class PaymentTermFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -58,12 +58,13 @@ class ProductFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$sort_col = explode('|', $sort);
if(!is_array($sort_col))
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
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
* @deprecated
*/
public function filter(string $filter = '') :Builder
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
@ -38,16 +38,29 @@ class ProjectFilters 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.
*
* @param string sort formatted as column|asc
* @return Illuminate\Eloquent\Query\Builder
*/
public function sort(string $sort) :Builder
public function sort(string $sort = ''): Builder
{
$sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
if(is_array($sort_col))
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
}
@ -57,7 +70,7 @@ class ProjectFilters extends QueryFilters
*
* @return Illuminate\Eloquent\Query\Builder
*/
public function entityFilter() :Builder
public function entityFilter(): Builder
{
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.
*
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}
@ -136,7 +149,7 @@ class PurchaseOrderFilters extends QueryFilters
*
* @return Builder
*/
private function contactViewFilter() : Builder
private function contactViewFilter(): Builder
{
return $this->builder
->whereCompanyId(auth()->guard('contact')->user()->company->id)

View File

@ -136,7 +136,7 @@ abstract class QueryFilters
* @param string filter
* @return Builder
*/
public function status(string $filter = '') : Builder
public function status(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
@ -241,7 +241,7 @@ abstract class QueryFilters
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) {
return $this->builder;
@ -250,7 +250,7 @@ abstract class QueryFilters
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) {
return $this->builder;

View File

@ -113,7 +113,11 @@ class QuoteFilters extends QueryFilters
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
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) {
return $this->builder;
}
if($sort_col[0] == 'valid_until')
$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.
*
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

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.
*
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

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.
*
* @param string sort formatted as column|asc
* @return Illuminate\Database\Eloquent\Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -42,10 +42,14 @@ class SubscriptionFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -18,18 +18,30 @@ use Illuminate\Database\Eloquent\Builder;
*/
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);
}
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);
}
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);
}
@ -40,7 +52,7 @@ class SystemLogFilters extends QueryFilters
* @return Builder
* @deprecated
*/
public function filter(string $filter = '') : Builder
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
@ -55,10 +67,14 @@ class SystemLogFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort) : Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -82,16 +82,29 @@ class TaskFilters extends QueryFilters
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.
*
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -42,10 +42,14 @@ class TaskStatusFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -25,7 +25,7 @@ class TaxRateFilters extends QueryFilters
* @return Builder
* @deprecated
*/
public function filter(string $filter = '') : Builder
public function filter(string $filter = ''): Builder
{
if (strlen($filter) == 0) {
return $this->builder;
@ -42,10 +42,14 @@ class TaxRateFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -42,10 +42,14 @@ class TokenFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -46,10 +46,14 @@ class UserFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}
@ -76,8 +80,9 @@ class UserFilters extends QueryFilters
public function with(string $value = ''): Builder
{
if(strlen($value) == 0)
if(strlen($value) == 0) {
return $this->builder;
}
return $this->builder
->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.
*
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -42,10 +42,14 @@ class WebhookFilters extends QueryFilters
* @param string sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort): Builder
public function sort(string $sort = ''): Builder
{
$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]);
}

View File

@ -73,7 +73,6 @@ class GmailTransport extends AbstractTransport
/* Need to slow down */
if($e->getCode() == '429') {
sleep(rand(5,10));
nlog("429 google - retrying ");
$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);
}
$cu->first()->account->companies->each(function ($company) use ($cu, $request) {
if ($company->tokens()->where('is_system', true)->count() == 0) {
(new CreateCompanyToken($company, $cu->first()->user, $request->server('HTTP_USER_AGENT')))->handle();
}
});
// $cu->first()->account->companies->each(function ($company) use ($cu, $request) {
// if ($company->tokens()->where('is_system', true)->count() == 0) {
// (new CreateCompanyToken($company, $cu->first()->user, $request->server('HTTP_USER_AGENT')))->handle();
// }
// });
if ($request->has('current_company') && $request->input('current_company') == 'true') {
$cu->where('company_id', $company_token->company_id);
@ -480,13 +480,13 @@ class LoginController extends BaseController
return $cu;
}
if (auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count()) {
auth()->user()->companies->each(function ($company) {
if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->exists()) {
(new CreateCompanyToken($company, auth()->user(), 'Google_O_Auth'))->handle();
}
});
}
// if (auth()->user()->company_users()->count() != auth()->user()->tokens()->distinct('company_id')->count()) {
// auth()->user()->companies->each(function ($company) {
// if (!CompanyToken::where('user_id', auth()->user()->id)->where('company_id', $company->id)->exists()) {
// (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());

View File

@ -267,7 +267,7 @@ class BaseController extends Controller
$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();
}
@ -633,7 +633,7 @@ class BaseController extends Controller
{
$user = auth()->user();
if ($user->getCompany()->is_large || $this->complexPermissionsUser()) {
if ($user->getCompany()->is_large) {
$this->manager->parseIncludes($this->mini_load);
return $this->miniLoadResponse($query);
@ -859,7 +859,7 @@ class BaseController extends Controller
'company.bank_transactions'=> function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at);
if (! $user->hasPermission('bank_transactions')) {
if (! $user->hasPermission('bank_transaction')) {
$query->where('bank_transactions.user_id', $user->id);
}
},

View File

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

View File

@ -150,11 +150,17 @@ class PaymentController extends Controller
$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);
if($invoices->sum('balance') > 0){
$invoice = $invoices->first();
$invoice->service()->touchPdf(true);
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)
{
$transformed_ids = $this->transformKeys($request->quotes);
nlog(request()->all());
if ($request->action == 'download') {
return $this->downloadQuotes((array) $transformed_ids);
@ -180,6 +181,14 @@ class QuoteController extends Controller
if ($process) {
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();
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();
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())

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)
{
$invitation = $this->credit_repository->getInvitationByKey($invitation_key);
if (! $invitation) {
return response()->json(['message' => 'no record found'], 400);
}
$credit = $invitation->credit;
$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('eloquent.updated: App\Models\Expense', $expense);
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('eloquent.created: App\Models\Expense', $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)));
// $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);
}

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));
event('eloquent.created: App\Models\Payment', $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('eloquent.updated: App\Models\Payment', $payment);
return $this->itemResponse($payment);
}

View File

@ -262,12 +262,14 @@ class ProjectController extends BaseController
$project->fill($request->all());
$project->number = empty($project->number) ? $this->getNextProjectNumber($project) : $project->number;
$project->save();
$project->saveQuietly();
if ($request->has('documents')) {
$this->saveDocuments($request->input('documents'), $project);
}
event('eloquent.updated: App\Models\Project', $project);
return $this->itemResponse($project->fresh());
}
@ -358,17 +360,19 @@ class ProjectController extends BaseController
{
$project = ProjectFactory::create(auth()->user()->company()->id, auth()->user()->id);
$project->fill($request->all());
$project->save();
$project->saveQuietly();
if (empty($project->number)) {
$project->number = $this->getNextProjectNumber($project);
$project->save();
$project->saveQuietly();
}
if ($request->has('documents')) {
$this->saveDocuments($request->input('documents'), $project);
}
event('eloquent.created: App\Models\Project', $project);
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)
{
$invitation = $this->quote_repo->getInvitationByKey($invitation_key);
if (! $invitation) {
return response()->json(['message' => 'no record found'], 400);
}
$contact = $invitation->contact;
$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('eloquent.updated: App\Models\Task', $task);
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('eloquent.created: App\Models\Task', $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('eloquent.updated: App\Models\Vendor', $vendor);
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('eloquent.created: App\Models\Vendor', $vendor);
return $this->itemResponse($vendor);
}

View File

@ -52,6 +52,7 @@ class InvoicesTable extends Component
$query = Invoice::query()
->where('company_id', $this->company->id)
->where('is_deleted', false)
->where('is_proforma', false)
->with('client.gateway_tokens', 'client.contacts')
->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\Models\ClientContact;
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\Str;
use Livewire\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 = [];
/**
@ -28,6 +51,9 @@ class RequiredClientInfo extends Component
*/
public $contact;
/**
* @var Client
*/
public $client;
/**
@ -60,6 +86,11 @@ class RequiredClientInfo extends Component
'client_shipping_postal_code' => 'shipping_postal_code',
'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_last_name' => 'last_name',
'contact_email' => 'email',
@ -100,6 +131,10 @@ class RequiredClientInfo extends Component
'client.name' => '',
'client.website' => '',
'client.phone' => '',
'client.custom_value1' => '',
'client.custom_value2' => '',
'client.custom_value3' => '',
'client.custom_value4' => '',
];
public $show_form = false;
@ -114,9 +149,28 @@ class RequiredClientInfo extends Component
$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->show_form = false;
}
public function toggleTermsAccepted()
{
$this->terms_accepted = !$this->terms_accepted;
}
public function handleSubmit(array $data): bool
@ -155,7 +209,7 @@ class RequiredClientInfo extends Component
private function updateClientDetails(array $data): bool
{
nlog($this->company->id);
$client = [];
$contact = [];
@ -215,6 +269,7 @@ class RequiredClientInfo extends Component
}
}
}
}
public function showCopyBillingCheckbox(): bool

View File

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

View File

@ -1,14 +1,21 @@
<?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;
use App\Models\Subscription;
use App\Utils\Traits\MakesHash;
use App\Exceptions\Ninja\ClientPortalAuthorizationException;
use Illuminate\Foundation\Http\FormRequest;
class ShowPlanSwitchRequest extends FormRequest
{
use MakesHash;
/**
* 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($record);
}
}
@ -368,7 +370,7 @@ class BaseImport
$payment_data['invoices'] = [
[
'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)
{
return (isset($data->$field) && $data->$field) ? (int)$data->$field : 0;

View File

@ -222,9 +222,10 @@ class InvoiceTransformer extends BaseTransformer
$record,
'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;
return $transformed;

View File

@ -52,17 +52,6 @@ class VendorTransformer extends BaseTransformer
'custom_value2' => $this->getString($data, 'vendor.custom_value2'),
'custom_value3' => $this->getString($data, 'vendor.custom_value3'),
'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' => [
[
'first_name' => $this->getString(
@ -70,7 +59,7 @@ class VendorTransformer extends BaseTransformer
'contact.first_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'),
'custom_value1' => $this->getString(
$data,

View File

@ -115,6 +115,7 @@ class CreateAccount
$spafe62e = isset($this->request['token_name']) ? $this->request['token_name'] : request()->server('HTTP_USER_AGENT');
$sp2d97e8 = (new CreateCompanyToken($sp035a66, $spaa9f78, $spafe62e))->handle();
if ($spaa9f78) {
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()
{
return [30, 60, 180, 240];
return [5, 10, 30, 240];
}
public function handle()
@ -176,19 +176,15 @@ class NinjaMailerJob implements ShouldQueue
* this merges a text string with a json object
* 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_body = json_decode($response->getBody()->getContents());
$message = "Either Attachment too large, or recipient has been suppressed.";
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->logMailError($e->getMessage(), $this->company->clients()->first());
$this->cleanUpMailers();
return;
}
@ -382,12 +378,14 @@ class NinjaMailerJob implements ShouldQueue
return $this->setMailDriver();
}
$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
->mailable
->from($user->email, $user->name());
->from($sending_email, $sending_user);
}
/**
@ -406,9 +404,12 @@ class NinjaMailerJob implements ShouldQueue
$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
->mailable
->from($user->email, $user->name());
->from($sending_email, $sending_user);
}
/**
@ -445,7 +446,6 @@ class NinjaMailerJob implements ShouldQueue
$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));
sleep(rand(1,6));
}
catch(\Exception $e) {
$this->logMailError('Gmail Token Invalid', $this->company->clients()->first());
@ -649,8 +648,9 @@ class NinjaMailerJob implements ShouldQueue
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;
use App\Libraries\MultiDB;
use App\Models\Account;
use App\Models\Client;
use App\Models\Company;
use Illuminate\Bus\Queueable;
@ -43,7 +44,7 @@ class CompanySizeCheck implements ShouldQueue
{
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) {
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 {
//multiDB environment, need to
foreach (MultiDB::$dbs as $db) {
@ -69,8 +86,8 @@ class CompanySizeCheck implements ShouldQueue
nlog("Company size check db {$db}");
Company::where('is_large', false)->withCount(['invoices', 'clients', 'products'])->cursor()->each(function ($company) {
if ($company->invoices_count > 500 || $company->products_count > 500 || $company->clients_count > 500) {
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 || $company->quotes_count > 500) {
nlog("Marking company {$company->id} as large");
$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->project_id = $this->invoice->project_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);
$this->quotes->each(function ($quote) {
$quote->service()->createInvitations();
(new CreateEntityPdf($quote->invitations()->first()))->handle();
});
try {

View File

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

View File

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

View File

@ -11,53 +11,34 @@
namespace App\Jobs\Util;
use App\Jobs\Util\SystemLogger;
use App\Jobs\Util\WebhookSingle;
use App\Libraries\MultiDB;
use App\Models\Client as ClientModel;
use App\Models\SystemLog;
use App\Models\Company;
use App\Models\Webhook;
use App\Transformers\ArraySerializer;
use App\Utils\Ninja;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
class WebhookHandler implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $entity;
private $event_id;
private $company;
public $tries = 1; //number of retries
public $deleteWhenMissingModels = true;
private string $includes;
/**
* Create a new job instance.
*
* @param $event_id
* @param $entity
*/
public function __construct($event_id, $entity, $company, $includes = '')
{
$this->event_id = $event_id;
$this->entity = $entity;
$this->company = $company;
$this->includes = $includes;
}
public function __construct(private int $event_id, private $entity, private Company $company, private string $includes = ''){}
/**
* Execute the job.
@ -74,12 +55,10 @@ class WebhookHandler implements ShouldQueue
return true;
}
$subscriptions = Webhook::where('company_id', $this->company->id)
->where('event_id', $this->event_id)
->cursor()
->each(function ($subscription) {
// $this->process($subscription);
Webhook::where('company_id', $this->company->id)
->where('event_id', $this->event_id)
->cursor()
->each(function ($subscription) {
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\Models\Client as ClientModel;
use App\Models\Company;
use App\Models\Product;
use App\Models\SystemLog;
use App\Models\Vendor;
use App\Models\Webhook;
use App\Transformers\ArraySerializer;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\RequestOptions;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@ -28,8 +32,6 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
class WebhookSingle implements ShouldQueue
{
@ -79,8 +81,14 @@ class WebhookSingle implements ShouldQueue
$subscription = Webhook::with('company')->find($this->subscription_id);
if($subscription)
nlog("firing event ID {$subscription->event_id}");
if(!$subscription){
$this->fail();
nlog("failed to fire event, could not find webhook ID {$this->subscription_id}");
return;
}
@ -235,19 +243,27 @@ class WebhookSingle implements ShouldQueue
}
private function resolveClient()
{
{ nlog(get_class($this->entity));
//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 &&
!$this->entity instanceof \App\Models\Vendor &&
!$this->entity instanceof \App\Models\Product &&
!$this->entity instanceof \App\Models\PurchaseOrder &&
$this->entity->client()->exists()) {
return $this->entity->client;
}
return $this->company->clients()->first();
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;
$this->activity_repo->save($fields, $event->client, $event->event_vars);
}
}

View File

@ -38,21 +38,18 @@ class CreateInvoicePdf implements ShouldQueue
if (isset($event->invoice)) {
$event->invoice->invitations->each(function ($invitation) {
// CreateEntityPdf::dispatch($invitation->load('invoice', 'contact.client.company'));
(new CreateEntityPdf($invitation->load('invoice', 'contact.client.company')))->handle();
});
}
if (isset($event->quote)) {
$event->quote->invitations->each(function ($invitation) {
// CreateEntityPdf::dispatch($invitation->load('quote', 'contact.client.company'));
(new CreateEntityPdf($invitation->load('quote', 'contact.client.company')))->handle();
});
}
if (isset($event->credit)) {
$event->credit->invitations->each(function ($invitation) {
// CreateEntityPdf::dispatch($invitation->load('credit', 'contact.client.company'));
(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\Models\Account;
use App\Models\Company;
use App\Notifications\Ninja\RenewalFailureNotification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Imdhemy\Purchases\Events\AppStore\DidRenew;
@ -38,10 +40,18 @@ class AppStoreRenewSubscription implements ShouldQueue
$inapp_transaction_id = $event->getSubscriptionId(); //$subscription_id
nlog("inapp upgrade processing for = {$inapp_transaction_id}");
MultiDB::findAndSetDbByInappTransactionId($inapp_transaction_id);
$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')
$account->plan_expires = now()->addMonth();
elseif($account->plan_term == 'year')

View File

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

View File

@ -18,6 +18,7 @@ use App\Utils\Ninja;
use App\Utils\Number;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class CreditEmailEngine extends BaseEmailEngine
{
@ -136,11 +137,19 @@ class CreditEmailEngine extends BaseEmailEngine
// Storage::url
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) {
$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 Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class InvoiceEmailEngine extends BaseEmailEngine
{
@ -136,13 +137,22 @@ class InvoiceEmailEngine extends BaseEmailEngine
//attach third party documents
if ($this->client->getSetting('document_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
// Storage::url
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) {
$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;
@ -160,7 +170,12 @@ class InvoiceEmailEngine extends BaseEmailEngine
->cursor()
->each(function ($expense) {
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()
->each(function ($task) {
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\Traits\MakesDates;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;
class PaymentEmailEngine extends BaseEmailEngine
{
@ -100,7 +101,11 @@ class PaymentEmailEngine extends BaseEmailEngine
if ($this->client->getSetting('document_email_attachment') !== false)
{
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 Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class PurchaseOrderEmailEngine extends BaseEmailEngine
{
@ -126,11 +127,6 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine
->setTextBody($text_body);
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();
@ -143,13 +139,19 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine
// Storage::url
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) {
$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 Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class QuoteEmailEngine extends BaseEmailEngine
{
@ -128,11 +129,19 @@ class QuoteEmailEngine extends BaseEmailEngine
// Storage::url
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) {
$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,
'whitelabel' => $this->client->user->account->isPaid() ? true : false,
'logo' => $this->company->present()->logo($settings),
'links' => $this->build_email->getAttachmentLinks(),
]);
foreach ($this->build_email->getAttachments() as $file) {

View File

@ -109,6 +109,7 @@ class VendorTemplateEmail extends Mailable
'company' => $this->company,
'whitelabel' => $this->vendor->user->account->isPaid() ? true : false,
'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 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

@ -70,16 +70,4 @@ class ClientGatewayToken extends BaseModel
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_contact_name',
'require_contact_email',
'require_custom_value1',
'require_custom_value2',
'require_custom_value3',
'require_custom_value4',
'update_details',
'config',
'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]);
}
// 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) {
$this->status_id = self::STATUS_APPLIED;
$this->save();
$this->saveQuietly();
return;
}
$this->save();
$this->saveQuietly();
}
public function setStatus($status)
{
$this->status_id = $status;
$this->save();
$this->saveQuietly();
}
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) {
if (! isset($invitation->sent_date)) {
$invitation->sent_date = Carbon::now();
$invitation->save();
$invitation->saveQuietly();
}
});
}

View File

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

View File

@ -14,14 +14,13 @@ namespace App\Models;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
class GroupSetting extends StaticModel
{
use MakesHash;
use SoftDeletes;
//public $timestamps = false;
protected $casts = [
'settings' => 'object',
'updated_at' => 'timestamp',
@ -65,4 +64,25 @@ class GroupSetting extends StaticModel
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);
}
// public function resolveRouteBinding($value, $field = null)
// {
// return $this
// ->withTrashed()
// ->where('id', $this->decodePrimaryKey($value))->firstOrFail();
// }
public function refund(array $data) :self
{
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()
{
@ -186,7 +190,7 @@ class PurchaseOrder extends BaseModel
$this->invitations->each(function ($invitation) {
if (! isset($invitation->sent_date)) {
$invitation->sent_date = Carbon::now();
$invitation->save();
$invitation->saveQuietly();
}
});
}

View File

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

View File

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

View File

@ -367,22 +367,41 @@ class User extends Authenticatable implements MustVerifyEmail
*/
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) {
$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() ||
$this->isAdmin() ||
(stripos($this->token()->cu->permissions, $permission) !== false) ||
(stripos($this->token()->cu->permissions, $all_permission) !== false) ||
(stripos($this->token()->cu->permissions, $permission) !== false);
// return $this->isOwner() ||
// $this->isAdmin() ||
// (is_int(stripos($this->token()->cu->permissions, $all_permission))) ||
// (is_int(stripos($this->token()->cu->permissions, $permission)));
(stripos($this->token()->cu->permissions, $edit_all) !== false) ||
(stripos($this->token()->cu->permissions, $edit_entity) !== false);
}

View File

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

View File

@ -18,47 +18,47 @@ class Webhook extends BaseModel
use SoftDeletes;
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;
@ -66,22 +66,86 @@ class Webhook extends BaseModel
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 = [
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_INVOICE,
self::EVENT_CREATE_QUOTE,
@ -112,7 +176,26 @@ class Webhook extends BaseModel
self::EVENT_UPDATE_CREDIT,
self::EVENT_DELETE_CREDIT,
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 = [

View File

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

View File

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

View File

@ -12,6 +12,7 @@
namespace App\Observers;
use App\Models\ClientContact;
use App\Models\CreditInvitation;
use App\Models\InvoiceInvitation;
use App\Models\QuoteInvitation;
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)
{
// $clientContact->invoice_invitations()->restore();
// $clientContact->quote_invitations()->restore();
// $clientContact->credit_invitations()->restore();
}
/**

View File

@ -17,6 +17,8 @@ use App\Models\Webhook;
class ClientObserver
{
public $afterCommit = true;
/**
* Handle the client "created" event.
*
@ -25,13 +27,13 @@ class ClientObserver
*/
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)
->exists();
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_CREATE_CLIENT, $client, $client->company)->delay(now()->addSeconds(2));
}
if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_CREATE_CLIENT, $client, $client->company)->delay(0);
}
/**
@ -42,51 +44,44 @@ class ClientObserver
*/
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();
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_UPDATE_CLIENT, $client, $client->company)->delay(now()->addSeconds(2));
}
if ($subscriptions)
WebhookHandler::dispatch($event, $client, $client->company)->delay(0);
}
/**
* Handle the client "deleted" event.
* Handle the client "archived" event.
*
* @param Client $client
* @return void
*/
public function deleted(Client $client)
{
$subscriptions = Webhook::where('company_id', $client->company->id)
->where('event_id', Webhook::EVENT_DELETE_CLIENT)
if($client->is_deleted)
return;
$subscriptions = Webhook::where('company_id', $client->company_id)
->where('event_id', Webhook::EVENT_ARCHIVE_CLIENT)
->exists();
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_DELETE_CLIENT, $client, $client->company)->delay(now()->addSeconds(2));
}
if ($subscriptions)
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
{
public $afterCommit = true;
/**
* Handle the client "created" event.
*
@ -27,12 +30,12 @@ class CreditObserver
*/
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)
->exists();
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)
{
$subscriptions = Webhook::where('company_id', $credit->company->id)
->where('event_id', Webhook::EVENT_UPDATE_CREDIT)
$event = 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();
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_UPDATE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2));
}
if ($subscriptions)
WebhookHandler::dispatch($event, $credit, $credit->company)->delay(0);
}
/**
@ -61,13 +72,16 @@ class CreditObserver
*/
public function deleted(Credit $credit)
{
$subscriptions = Webhook::where('company_id', $credit->company->id)
->where('event_id', Webhook::EVENT_DELETE_CREDIT)
if($credit->is_deleted)
return;
$subscriptions = Webhook::where('company_id', $credit->company_id)
->where('event_id', Webhook::EVENT_ARCHIVE_CREDIT)
->exists();
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_DELETE_CREDIT, $credit, $credit->company)->delay(now()->addSeconds(2));
}
if ($subscriptions)
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
{
public $afterCommit = true;
/**
* Handle the expense "created" event.
*
@ -25,13 +27,13 @@ class ExpenseObserver
*/
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)
->exists();
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_CREATE_EXPENSE, $expense, $expense->company)->delay(now()->addSeconds(2));
}
if ($subscriptions)
WebhookHandler::dispatch(Webhook::EVENT_CREATE_EXPENSE, $expense, $expense->company)->delay(0);
}
/**
@ -42,13 +44,22 @@ class ExpenseObserver
*/
public function updated(Expense $expense)
{
$subscriptions = Webhook::where('company_id', $expense->company->id)
->where('event_id', Webhook::EVENT_UPDATE_EXPENSE)
->exists();
$event = Webhook::EVENT_UPDATE_EXPENSE;
if($expense->getOriginal('deleted_at') && !$expense->deleted_at)
$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);
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_UPDATE_EXPENSE, $expense, $expense->company)->delay(now()->addSeconds(2));
}
}
/**
@ -59,13 +70,16 @@ class ExpenseObserver
*/
public function deleted(Expense $expense)
{
$subscriptions = Webhook::where('company_id', $expense->company->id)
->where('event_id', Webhook::EVENT_DELETE_EXPENSE)
if($expense->is_deleted)
return;
$subscriptions = Webhook::where('company_id', $expense->company_id)
->where('event_id', Webhook::EVENT_ARCHIVE_EXPENSE)
->exists();
if ($subscriptions) {
WebhookHandler::dispatch(Webhook::EVENT_DELETE_EXPENSE, $expense, $expense->company)->delay(now()->addSeconds(2));
}
if ($subscriptions)
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