Merge remote-tracking branch 'upstream/v5-develop' into laravel11

This commit is contained in:
Benjamin Beganović 2024-06-18 13:06:41 +02:00
commit abc57ed625
537 changed files with 196392 additions and 194247 deletions

View File

@ -23,4 +23,5 @@ API_SECRET=superdoopersecrethere
PHANTOMJS_PDF_GENERATION=false PHANTOMJS_PDF_GENERATION=false
CACHE_DRIVER=redis CACHE_DRIVER=redis
QUEUE_CONNECTION=redis QUEUE_CONNECTION=redis
SESSION_DRIVER=redis SESSION_DRIVER=redis
PDF_GENERATOR=hosted_ninja

View File

@ -44,6 +44,7 @@ jobs:
git clone https://${{secrets.commit_secret}}@github.com/invoiceninja/ui.git git clone https://${{secrets.commit_secret}}@github.com/invoiceninja/ui.git
cd ui cd ui
git checkout develop git checkout develop
cp ../vite.config.ts.react ./vite.config.js
npm i npm i
npm run build npm run build
cp -r dist/* ../public/ cp -r dist/* ../public/
@ -60,7 +61,8 @@ jobs:
sudo rm -rf node_modules sudo rm -rf node_modules
sudo rm -rf .git sudo rm -rf .git
sudo rm .env sudo rm .env
sudo rm -rf ui
- name: Build project - name: Build project
run: | run: |
shopt -s dotglob shopt -s dotglob

View File

@ -72,7 +72,6 @@ jobs:
- name: Build project - name: Build project
run: | run: |
zip -r /home/runner/work/invoiceninja/invoiceninja.zip .* -x "../*"
shopt -s dotglob shopt -s dotglob
tar --exclude='public/storage' --exclude='./htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/invoiceninja.tar * tar --exclude='public/storage' --exclude='./htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/invoiceninja.tar *
- name: Release - name: Release
@ -82,5 +81,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
files: | files: |
/home/runner/work/invoiceninja/invoiceninja.tar /home/runner/work/invoiceninja/invoiceninja.tar
/home/runner/work/invoiceninja/invoiceninja.zip

View File

@ -1 +1 @@
5.9.2 5.9.9

View File

@ -176,6 +176,7 @@ class BackupUpdate extends Command
try { try {
$doc_bin = $document->getFile(); $doc_bin = $document->getFile();
} catch(\Exception $e) { } catch(\Exception $e) {
nlog("Exception:: BackupUpdate::" . $e->getMessage());
nlog($e->getMessage()); nlog($e->getMessage());
} }
@ -184,8 +185,6 @@ class BackupUpdate extends Command
$document->disk = $this->option('disk'); $document->disk = $this->option('disk');
$document->saveQuietly(); $document->saveQuietly();
nlog("Documents - Moving {$document->url} to {$this->option('disk')}");
} }
}); });
@ -199,8 +198,6 @@ class BackupUpdate extends Command
if ($backup_bin) { if ($backup_bin) {
Storage::disk($this->option('disk'))->put($backup->filename, $backup_bin); Storage::disk($this->option('disk'))->put($backup->filename, $backup_bin);
nlog("Backups - Moving {$backup->filename} to {$this->option('disk')}");
} }
}); });
} }

View File

@ -172,18 +172,18 @@ class CheckData extends Command
CompanyUser::query()->cursor()->each(function ($cu) { CompanyUser::query()->cursor()->each(function ($cu) {
if (CompanyToken::where('user_id', $cu->user_id)->where('company_id', $cu->company_id)->where('is_system', 1)->doesntExist()) { if (CompanyToken::where('user_id', $cu->user_id)->where('company_id', $cu->company_id)->where('is_system', 1)->doesntExist()) {
if ($cu->company && $cu->user) { if ($cu->company && $cu->user) {
$this->logMessage("Creating missing company token for user # {$cu->user_id} for company id # {$cu->company_id}"); $this->logMessage("Creating missing company token for user # {$cu->user_id} for company id # {$cu->company_id}");
(new CreateCompanyToken($cu->company, $cu->user, 'System'))->handle(); (new CreateCompanyToken($cu->company, $cu->user, 'System'))->handle();
} }
if (!$cu->user) { if (!$cu->user) {
$this->logMessage("No user found for company user - removing company user"); $this->logMessage("No user found for company user - removing company user");
$cu->forceDelete(); $cu->forceDelete();
} }
} }
}); });
} }
@ -477,14 +477,13 @@ class CheckData extends Command
} }
} else { } else {
$this->logMessage("No contact present, so cannot add invitation for {$entity_key} - {$entity->id}"); $this->logMessage("No contact present, so cannot add invitation for {$entity_key} - {$entity->id}");
try{ try {
$entity->service()->createInvitations()->save(); $entity->service()->createInvitations()->save();
} } catch(\Exception $e) {
catch(\Exception $e){
} }
} }
try { try {
@ -949,12 +948,12 @@ class CheckData extends Command
}); });
Company::whereDoesntHave('company_users', function ($query){ Company::whereDoesntHave('company_users', function ($query) {
$query->where('is_owner', 1); $query->where('is_owner', 1);
}) })
->cursor() ->cursor()
->when(Ninja::isHosted()) ->when(Ninja::isHosted())
->each(function ($c){ ->each(function ($c) {
$this->logMessage("Orphan Account # {$c->account_id}"); $this->logMessage("Orphan Account # {$c->account_id}");
@ -963,8 +962,8 @@ class CheckData extends Command
CompanyUser::whereDoesntHave('tokens') CompanyUser::whereDoesntHave('tokens')
->cursor() ->cursor()
->when(Ninja::isHosted()) ->when(Ninja::isHosted())
->each(function ($cu){ ->each(function ($cu) {
$this->logMessage("Missing tokens for Company User # {$cu->id}"); $this->logMessage("Missing tokens for Company User # {$cu->id}");
}); });

View File

@ -1016,7 +1016,7 @@ class CreateSingleAccount extends Command
$cg->fees_and_limits = $fees_and_limits; $cg->fees_and_limits = $fees_and_limits;
$cg->save(); $cg->save();
} }
if (config('ninja.testvars.eway') && ($this->gateway == 'all' || $this->gateway == 'eway')) { if (config('ninja.testvars.eway') && ($this->gateway == 'all' || $this->gateway == 'eway')) {
$cg = new CompanyGateway(); $cg = new CompanyGateway();
$cg->company_id = $company->id; $cg->company_id = $company->id;
@ -1038,12 +1038,12 @@ class CreateSingleAccount extends Command
$cg->save(); $cg->save();
} }
if (config('ninja.testvars.gocardless') && ($this->gateway == 'all' || $this->gateway == 'gocardless')) { if (config('ninja.testvars.gocardless') && ($this->gateway == 'all' || $this->gateway == 'gocardless')) {
$c_settings = ClientSettings::defaults(); $c_settings = ClientSettings::defaults();
$c_settings->currency_id = '2'; $c_settings->currency_id = '2';
$client = Client::factory()->create([ $client = Client::factory()->create([
'user_id' => $user->id, 'user_id' => $user->id,
'company_id' => $company->id, 'company_id' => $company->id,

View File

@ -48,37 +48,37 @@ class ReactBuilder extends Command
{ {
if($this->option('type') == 'local') { if($this->option('type') == 'local') {
$includes = '';
$directoryIterator = false; $includes = '';
try { $directoryIterator = false;
$directoryIterator = new \RecursiveDirectoryIterator(public_path('react/v'.config('ninja.app_version').'/'), \RecursiveDirectoryIterator::SKIP_DOTS);
} catch (\Exception $e) {
$this->error('React files not found');
return;
}
foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) { try {
if ($file->getExtension() == 'js') { $directoryIterator = new \RecursiveDirectoryIterator(public_path('react/v'.config('ninja.app_version').'/'), \RecursiveDirectoryIterator::SKIP_DOTS);
if (str_contains($file->getFileName(), 'index-')) { } catch (\Exception $e) {
$includes .= '<script type="module" crossorigin src="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'"></script>'."\n"; $this->error('React files not found');
} else { return;
$includes .= '<link rel="modulepreload" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n"; }
foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) {
if ($file->getExtension() == 'js') {
if (str_contains($file->getFileName(), 'index-')) {
$includes .= '<script type="module" crossorigin src="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'"></script>'."\n";
} else {
$includes .= '<link rel="modulepreload" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n";
}
}
if (str_contains($file->getFileName(), '.css')) {
$includes .= '<link rel="stylesheet" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n";
} }
} }
if (str_contains($file->getFileName(), '.css')) { file_put_contents(resource_path('views/react/head.blade.php'), $includes);
$includes .= '<link rel="stylesheet" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n";
}
}
file_put_contents(resource_path('views/react/head.blade.php'), $includes);
} }
} }
} }

View File

@ -55,7 +55,7 @@ class DbQuery extends GenericMixedMetric
public $string_metric8 = 'client_version'; public $string_metric8 = 'client_version';
public $string_metric9 = 'platform'; public $string_metric9 = 'platform';
/** /**
* The counter * The counter
* set to 1. * set to 1.
@ -66,12 +66,14 @@ class DbQuery extends GenericMixedMetric
public $double_metric2 = 1; public $double_metric2 = 1;
public function __construct($string_metric5, $string_metric6, $int_metric1, $double_metric2, $string_metric7) public function __construct($string_metric5, $string_metric6, $int_metric1, $double_metric2, $string_metric7, $string_metric8, $string_metric9)
{ {
$this->int_metric1 = $int_metric1; $this->int_metric1 = $int_metric1;
$this->string_metric5 = $string_metric5; $this->string_metric5 = $string_metric5;
$this->string_metric6 = $string_metric6; $this->string_metric6 = $string_metric6;
$this->double_metric2 = $double_metric2; $this->double_metric2 = $double_metric2;
$this->string_metric7 = $string_metric7; $this->string_metric7 = $string_metric7;
$this->string_metric8 = $string_metric8;
$this->string_metric9 = $string_metric9;
} }
} }

View File

@ -0,0 +1,61 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Analytics;
use Turbo124\Beacon\ExampleMetric\GenericMixedMetric;
class LoginMeta extends GenericMixedMetric
{
/**
* The type of Sample.
*
* Monotonically incrementing counter
*
* - counter
*
* @var string
*/
public $type = 'mixed_metric';
/**
* The name of the counter.
* @var string
*/
public $name = 'login.meta';
/**
* The datetime of the counter measurement.
*
* date("Y-m-d H:i:s")
*
*/
public $datetime;
/**
* The Class failure name
* set to 0.
*
* @var string
*/
public $string_metric5 = 'email';
public $string_metric6 = 'ip';
public $string_metric7 = 'result';
public $int_metric1 = 1;
public function __construct($string_metric5, $string_metric6, $string_metric7)
{
$this->string_metric7 = $string_metric7;
$this->string_metric6 = $string_metric6;
$this->string_metric5 = $string_metric5;
}
}

View File

@ -29,7 +29,7 @@ class CompanySettings extends BaseSettings
public $besr_id = ''; //@implemented public $besr_id = ''; //@implemented
public $lock_invoices = 'off'; //off,when_sent,when_paid //@implemented public $lock_invoices = 'off'; //off,when_sent,when_paid,end_of_month //@implemented
public $enable_client_portal_tasks = false; //@ben to implement public $enable_client_portal_tasks = false; //@ben to implement

View File

@ -64,9 +64,9 @@ class InvoiceItem
public $task_id = ''; public $task_id = '';
public $expense_id = ''; public $expense_id = '';
public $unit_code = 'C62'; public $unit_code = 'C62';
public static $casts = [ public static $casts = [
'task_id' => 'string', 'task_id' => 'string',
'expense_id' => 'string', 'expense_id' => 'string',

View File

@ -15,7 +15,6 @@ use App\DataMapper\InvoiceItem;
class PayPalBalanceAffecting class PayPalBalanceAffecting
{ {
private array $key_map = [ private array $key_map = [
'Date' => 'date', 'Date' => 'date',
'Time' => 'time', 'Time' => 'time',
@ -105,8 +104,10 @@ class PayPalBalanceAffecting
public $discount; public $discount;
public $creditTransactionalFee; public $creditTransactionalFee;
public $originalInvoiceId; public $originalInvoiceId;
public function __construct(private array $import_row){} public function __construct(private array $import_row)
{
}
public function run(): self public function run(): self
{ {
@ -116,11 +117,11 @@ class PayPalBalanceAffecting
$prop = $this->key_map[$key] ?? false; $prop = $this->key_map[$key] ?? false;
if($prop){ if($prop) {
echo "Setting {$prop} to {$value}".PHP_EOL; echo "Setting {$prop} to {$value}".PHP_EOL;
$this->{$prop} = $value; $this->{$prop} = $value;
} }
} }
@ -130,7 +131,7 @@ class PayPalBalanceAffecting
private function cleanUp(): self private function cleanUp(): self
{ {
foreach($this->key_map as $value){ foreach($this->key_map as $value) {
echo "Setting {$value} to null".PHP_EOL; echo "Setting {$value} to null".PHP_EOL;
$this->{$value} = null; $this->{$value} = null;
} }
@ -154,7 +155,7 @@ class PayPalBalanceAffecting
public function getInvoice(): array public function getInvoice(): array
{ {
$item = new InvoiceItem; $item = new InvoiceItem();
$item->cost = $this->gross ?? 0; $item->cost = $this->gross ?? 0;
$item->product_key = $this->itemId ?? ''; $item->product_key = $this->itemId ?? '';
$item->notes = $this->subject ?? $this->itemDetails; $item->notes = $this->subject ?? $this->itemDetails;
@ -162,7 +163,7 @@ class PayPalBalanceAffecting
return [ return [
'number' => trim($this->invoiceNumber ?? $this->transactionId), 'number' => trim($this->invoiceNumber ?? $this->transactionId),
'date' => str_replace('/','-', $this->date ?? ''), 'date' => str_replace('/', '-', $this->date ?? ''),
'line_items' => [$item], 'line_items' => [$item],
'name' => $this->name ?? '', 'name' => $this->name ?? '',
'email' => $this->fromEmailAddress ?? '', 'email' => $this->fromEmailAddress ?? '',
@ -174,12 +175,10 @@ class PayPalBalanceAffecting
{ {
$name_parts = explode(" ", $this->name ?? ''); $name_parts = explode(" ", $this->name ?? '');
if(count($name_parts) == 2) if(count($name_parts) == 2) {
{
$contact['first_name'] = $name_parts[0]; $contact['first_name'] = $name_parts[0];
$contact['last_name'] = $name_parts[1]; $contact['last_name'] = $name_parts[1];
} } else {
else {
$contact['first_name'] = $this->name ?? ''; $contact['first_name'] = $this->name ?? '';
} }
@ -188,7 +187,7 @@ class PayPalBalanceAffecting
return $contact; return $contact;
} }
private function returnAddress(): array private function returnAddress(): array
{ {
return [ return [
@ -203,13 +202,15 @@ class PayPalBalanceAffecting
private function returnShippingAddress(): array private function returnShippingAddress(): array
{ {
if(strlen($this->shippingAddress ?? '') <3) if(strlen($this->shippingAddress ?? '') < 3) {
return []; return [];
}
$ship_parts = explode(",", $this->shippingAddress); $ship_parts = explode(",", $this->shippingAddress);
if(count($ship_parts) != 7) if(count($ship_parts) != 7) {
return []; return [];
}
return [ return [
'shipping_address1' => $ship_parts[2], 'shipping_address1' => $ship_parts[2],

View File

@ -220,6 +220,7 @@ class BaseRule implements RuleInterface
try { try {
$this->invoice->saveQuietly(); $this->invoice->saveQuietly();
} catch(\Exception $e) { } catch(\Exception $e) {
nlog("Exception:: BaseRule::" . $e->getMessage());
} }
} }

View File

@ -24,6 +24,7 @@ class TaxData
public function __construct(public Response $origin) public function __construct(public Response $origin)
{ {
// @phpstan-ignore-next-line
foreach($origin as $key => $value) { foreach($origin as $key => $value) {
$this->{$key} = $value; $this->{$key} = $value;
} }

View File

@ -1,24 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataProviders;
/**
* Class FACT1.
*/
class FACT1
{
public function build()
{
$i = new \InvoiceNinja\EInvoice\Models\FACT1\Invoice();
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Exceptions;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DuplicatePaymentException extends Exception
{
/**
* Report the exception.
*
* @return void
*/
public function report()
{
//
}
/**
* Render the exception into an HTTP response.
*
* @param Request $request
* @return JsonResponse
*/
public function render($request)
{
return response()->json([
'message' => 'Duplicate request',
], 400);
}
}

View File

@ -109,10 +109,11 @@ class Handler extends ExceptionHandler
Integration::configureScope(function (Scope $scope): void { Integration::configureScope(function (Scope $scope): void {
$name = 'hosted@invoiceninja.com'; $name = 'hosted@invoiceninja.com';
if (auth()->guard('contact') && auth()->guard('contact')->user()) { if (auth()->guard('contact') && auth()->guard('contact')->user()) { // @phpstan-ignore-line
$name = 'Contact = '.auth()->guard('contact')->user()->email; $name = 'Contact = '.auth()->guard('contact')->user()->email;
$key = auth()->guard('contact')->user()->company->account->key; $key = auth()->guard('contact')->user()->company->account->key;
} elseif (auth()->guard('user') && auth()->guard('user')->user()) { } elseif (auth()->guard('user') && auth()->guard('user')->user()) { // @phpstan-ignore-line
$name = 'Admin = '.auth()->guard('user')->user()->email; $name = 'Admin = '.auth()->guard('user')->user()->email;
$key = auth()->user()->account->key; $key = auth()->user()->account->key;
} else { } else {
@ -131,13 +132,14 @@ class Handler extends ExceptionHandler
} }
} elseif (app()->bound('sentry')) { } elseif (app()->bound('sentry')) {
Integration::configureScope(function (Scope $scope): void { Integration::configureScope(function (Scope $scope): void {
if (auth()->guard('contact') && auth()->guard('contact')->user() && auth()->guard('contact')->user()->company->account->report_errors) { if (auth()->guard('contact') && auth()->guard('contact')->user() && auth()->guard('contact')->user()->company->account->report_errors) {// @phpstan-ignore-line
$scope->setUser([ $scope->setUser([
'id' => auth()->guard('contact')->user()->company->account->key, 'id' => auth()->guard('contact')->user()->company->account->key,
'email' => 'anonymous@example.com', 'email' => 'anonymous@example.com',
'name' => 'Anonymous User', 'name' => 'Anonymous User',
]); ]);
} elseif (auth()->guard('user') && auth()->guard('user')->user() && auth()->user()->companyIsSet() && auth()->user()->company()->account->report_errors) { } elseif (auth()->guard('user') && auth()->guard('user')->user() && auth()->user()->companyIsSet() && auth()->user()->company()->account->report_errors) {// @phpstan-ignore-line
$scope->setUser([ $scope->setUser([
'id' => auth()->user()->account->key, 'id' => auth()->user()->account->key,
'email' => 'anonymous@example.com', 'email' => 'anonymous@example.com',

View File

@ -25,8 +25,6 @@ use League\Csv\Writer;
class ActivityExport extends BaseExport class ActivityExport extends BaseExport
{ {
private $entity_transformer;
public string $date_key = 'created_at'; public string $date_key = 'created_at';
private string $date_format = 'YYYY-MM-DD'; private string $date_format = 'YYYY-MM-DD';
@ -43,7 +41,7 @@ class ActivityExport extends BaseExport
{ {
$this->company = $company; $this->company = $company;
$this->input = $input; $this->input = $input;
$this->entity_transformer = new ActivityTransformer();
} }
public function returnJson() public function returnJson()
@ -143,10 +141,10 @@ class ActivityExport extends BaseExport
} }
private function decorateAdvancedFields(Task $task, array $entity): array // private function decorateAdvancedFields(Task $task, array $entity): array
{ // {
return $entity; // return $entity;
} // }
public function processMetaData(array $row, $resource): array public function processMetaData(array $row, $resource): array

View File

@ -838,12 +838,12 @@ class BaseExport
return ''; return '';
} }
/** /**
* Apply Product Filters * Apply Product Filters
* *
* @param Builder $query * @param Builder $query
* *
* @return Builder * @return Builder
*/ */
public function applyProductFilters(Builder $query): Builder public function applyProductFilters(Builder $query): Builder
@ -863,13 +863,13 @@ class BaseExport
return $query; return $query;
} }
/** /**
* Add Client Filter * Add Client Filter
* *
* @param Builder $query * @param Builder $query
* @param mixed $clients * @param mixed $clients
* *
* @return Builder * @return Builder
*/ */
protected function addClientFilter(Builder $query, $clients): Builder protected function addClientFilter(Builder $query, $clients): Builder
@ -886,13 +886,13 @@ class BaseExport
return $query; return $query;
} }
/** /**
* Add Vendor Filter * Add Vendor Filter
* *
* @param Builder $query * @param Builder $query
* @param string $vendors * @param string $vendors
* *
* @return Builder * @return Builder
*/ */
protected function addVendorFilter(Builder$query, string $vendors): Builder protected function addVendorFilter(Builder$query, string $vendors): Builder
@ -910,13 +910,13 @@ class BaseExport
return $query; return $query;
} }
/** /**
* AddProjectFilter * AddProjectFilter
* *
* @param Builder $query * @param Builder $query
* @param string $projects * @param string $projects
* *
* @return Builder * @return Builder
*/ */
protected function addProjectFilter(Builder $query, string $projects): Builder protected function addProjectFilter(Builder $query, string $projects): Builder
@ -934,13 +934,13 @@ class BaseExport
return $query; return $query;
} }
/** /**
* Add Category Filter * Add Category Filter
* *
* @param Builder $query * @param Builder $query
* @param string $expense_categories * @param string $expense_categories
* *
* @return Builder * @return Builder
*/ */
protected function addCategoryFilter(Builder $query, string $expense_categories): Builder protected function addCategoryFilter(Builder $query, string $expense_categories): Builder
@ -959,24 +959,25 @@ class BaseExport
return $query; return $query;
} }
/** /**
* Add Payment Status Filters * Add Payment Status Filters
* *
* @param Builder $query * @param Builder $query
* @param string $status * @param string $status
* *
* @return Builder * @return Builder
*/ */
protected function addPaymentStatusFilters(Builder $query, string $status): Builder protected function addPaymentStatusFilters(Builder $query, string $status): Builder
{ {
/** @var array $status_parameters */
$status_parameters = explode(',', $status); $status_parameters = explode(',', $status);
if(in_array('all', $status_parameters) || count($status_parameters) == 0) { if((count($status_parameters) == 0) || in_array('all', $status_parameters)) {
return $query; return $query;
} }
$query->where(function ($query) use ($status_parameters) { $query->where(function ($query) use ($status_parameters) {
$payment_filters = []; $payment_filters = [];
@ -1016,21 +1017,22 @@ class BaseExport
return $query; return $query;
} }
/** /**
* Add RecurringInvoice Status Filter * Add RecurringInvoice Status Filter
* *
* @param Builder $query * @param Builder $query
* @param string $status * @param string $status
* *
* @return Builder * @return Builder
*/ */
protected function addRecurringInvoiceStatusFilter(Builder $query, string $status): Builder protected function addRecurringInvoiceStatusFilter(Builder $query, string $status): Builder
{ {
/** @var array $status_parameters */
$status_parameters = explode(',', $status); $status_parameters = explode(',', $status);
if (in_array('all', $status_parameters) || count($status_parameters) == 0){ if (in_array('all', $status_parameters) || count($status_parameters) == 0) {
return $query; return $query;
} }
@ -1060,7 +1062,7 @@ class BaseExport
* *
* @param Builder $query * @param Builder $query
* @param string $status * @param string $status
* *
* @return Builder * @return Builder
*/ */
protected function addQuoteStatusFilter(Builder $query, string $status): Builder protected function addQuoteStatusFilter(Builder $query, string $status): Builder
@ -1126,12 +1128,13 @@ class BaseExport
* *
* @param Builder $query * @param Builder $query
* @param string $status * @param string $status
* *
* @return Builder * @return Builder
*/ */
protected function addPurchaseOrderStatusFilter(Builder $query, string $status): Builder protected function addPurchaseOrderStatusFilter(Builder $query, string $status): Builder
{ {
/** @var array $status_parameters */
$status_parameters = explode(',', $status); $status_parameters = explode(',', $status);
if (in_array('all', $status_parameters) || count($status_parameters) == 0) { if (in_array('all', $status_parameters) || count($status_parameters) == 0) {
@ -1179,7 +1182,8 @@ class BaseExport
*/ */
protected function addInvoiceStatusFilter(Builder $query, string $status): Builder protected function addInvoiceStatusFilter(Builder $query, string $status): Builder
{ {
/** @var array $status_parameters */
$status_parameters = explode(',', $status); $status_parameters = explode(',', $status);
if(in_array('all', $status_parameters) || count($status_parameters) == 0) { if(in_array('all', $status_parameters) || count($status_parameters) == 0) {
@ -1234,7 +1238,7 @@ class BaseExport
return $query; return $query;
} }
/** /**
* Add Date Range * Add Date Range
* *
@ -1578,7 +1582,7 @@ class BaseExport
public function queueDocuments(Builder $query) public function queueDocuments(Builder $query)
{ {
if($query->getModel() instanceof Document) { if($query->getModel() instanceof Document) {
$documents = $query->pluck('id')->toArray(); $documents = $query->pluck('id')->toArray();
} else { } else {

View File

@ -127,8 +127,9 @@ class ClientExport extends BaseExport
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false) if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
}
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
@ -242,16 +243,16 @@ class ClientExport extends BaseExport
return $entity; return $entity;
} }
private function calculateStatus($client) // private function calculateStatus($client)
{ // {
if ($client->is_deleted) { // if ($client->is_deleted) {
return ctrans('texts.deleted'); // return ctrans('texts.deleted');
} // }
if ($client->deleted_at) { // if ($client->deleted_at) {
return ctrans('texts.archived'); // return ctrans('texts.archived');
} // }
return ctrans('texts.active'); // return ctrans('texts.active');
} // }
} }

View File

@ -59,7 +59,7 @@ class ContactExport extends BaseExport
$query = ClientContact::query() $query = ClientContact::query()
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}); });
@ -155,7 +155,7 @@ class ContactExport extends BaseExport
} }
if (in_array('client.user_id', $this->input['report_keys'])) { if (in_array('client.user_id', $this->input['report_keys'])) {
$entity['client.user_id'] = $client->user ? $client->user->present()->name() : ''; $entity['client.user_id'] = $client->user ? $client->user->present()->name() : '';// @phpstan-ignore-line
} }
if (in_array('client.assigned_user_id', $this->input['report_keys'])) { if (in_array('client.assigned_user_id', $this->input['report_keys'])) {

View File

@ -102,7 +102,7 @@ class CreditExport extends BaseExport
$query = Credit::query() $query = Credit::query()
->withTrashed() ->withTrashed()
->with('client') ->with('client')
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)

View File

@ -83,9 +83,9 @@ class ExpenseExport extends BaseExport
->with('client') ->with('client')
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }
@ -220,17 +220,17 @@ class ExpenseExport extends BaseExport
// $entity['expense.client'] = $expense->client ? $expense->client->present()->name() : ''; // $entity['expense.client'] = $expense->client ? $expense->client->present()->name() : '';
// } // }
// if (in_array('expense.invoice_id', $this->input['report_keys'])) { if (in_array('expense.invoice_id', $this->input['report_keys'])) {
// $entity['expense.invoice_id'] = $expense->invoice ? $expense->invoice->number : ''; $entity['expense.invoice_id'] = $expense->invoice ? $expense->invoice->number : '';
// } }
// if (in_array('expense.category', $this->input['report_keys'])) { // if (in_array('expense.category', $this->input['report_keys'])) {
// $entity['expense.category'] = $expense->category ? $expense->category->name : ''; // $entity['expense.category'] = $expense->category ? $expense->category->name : '';
// } // }
// if (in_array('expense.vendor_id', $this->input['report_keys'])) { if (in_array('expense.vendor_id', $this->input['report_keys'])) {
// $entity['expense.vendor'] = $expense->vendor ? $expense->vendor->name : ''; $entity['expense.vendor'] = $expense->vendor ? $expense->vendor->name : '';
// } }
// if (in_array('expense.payment_type_id', $this->input['report_keys'])) { // if (in_array('expense.payment_type_id', $this->input['report_keys'])) {
// $entity['expense.payment_type_id'] = $expense->payment_type ? $expense->payment_type->name : ''; // $entity['expense.payment_type_id'] = $expense->payment_type ? $expense->payment_type->name : '';

View File

@ -57,13 +57,13 @@ class InvoiceExport extends BaseExport
$query = Invoice::query() $query = Invoice::query()
->withTrashed() ->withTrashed()
->with('client') ->with('client')
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){
if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }

View File

@ -70,12 +70,12 @@ class InvoiceItemExport extends BaseExport
$query = Invoice::query() $query = Invoice::query()
->withTrashed() ->withTrashed()
->with('client') ->with('client')
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }

View File

@ -56,7 +56,7 @@ class PaymentExport extends BaseExport
$query = Payment::query() $query = Payment::query()
->withTrashed() ->withTrashed()
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
@ -71,7 +71,7 @@ class PaymentExport extends BaseExport
} }
$query = $this->addPaymentStatusFilters($query, $this->input['status'] ?? ''); $query = $this->addPaymentStatusFilters($query, $this->input['status'] ?? '');
if($this->input['document_email_attachment'] ?? false) { if($this->input['document_email_attachment'] ?? false) {
$this->queueDocuments($query); $this->queueDocuments($query);
} }

View File

@ -74,9 +74,9 @@ class ProductExport extends BaseExport
$query = Product::query() $query = Product::query()
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }
@ -133,16 +133,16 @@ class ProductExport extends BaseExport
// return $this->decorateAdvancedFields($product, $entity); // return $this->decorateAdvancedFields($product, $entity);
} }
private function decorateAdvancedFields(Product $product, array $entity): array // private function decorateAdvancedFields(Product $product, array $entity): array
{ // {
if (in_array('vendor_id', $this->input['report_keys'])) { // if (in_array('vendor_id', $this->input['report_keys'])) {
$entity['vendor'] = $product->vendor()->exists() ? $product->vendor->name : ''; // $entity['vendor'] = $product->vendor()->exists() ? $product->vendor->name : '';
} // }
// if (array_key_exists('project_id', $this->input['report_keys'])) { // // if (array_key_exists('project_id', $this->input['report_keys'])) {
// $entity['project'] = $product->project()->exists() ? $product->project->name : ''; // // $entity['project'] = $product->project()->exists() ? $product->project->name : '';
// } // // }
return $entity; // return $entity;
} // }
} }

View File

@ -25,6 +25,7 @@ class ProductSalesExport extends BaseExport
{ {
public string $date_key = 'created_at'; public string $date_key = 'created_at';
/** @var Collection<\App\Models\Product> $products*/
protected Collection $products; protected Collection $products;
public Writer $csv; public Writer $csv;
@ -65,11 +66,11 @@ class ProductSalesExport extends BaseExport
'custom_value4' => 'custom_value4', 'custom_value4' => 'custom_value4',
]; ];
private array $decorate_keys = [ // private array $decorate_keys = [
'client', // 'client',
'currency', // 'currency',
'date', // 'date',
]; // ];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
@ -80,20 +81,20 @@ class ProductSalesExport extends BaseExport
public function filterByProducts($query) public function filterByProducts($query)
{ {
$product_keys = &$this->input['product_key']; $product_keys = &$this->input['product_key'];
if ($product_keys && !empty($this->input['product_key'])) { if ($product_keys && !empty($this->input['product_key'])) {
$keys = explode(",", $product_keys); $keys = explode(",", $product_keys);
$query->where(function ($q) use ($keys){ $query->where(function ($q) use ($keys) {
foreach($keys as $key) { foreach($keys as $key) {
$q->orWhereJsonContains('line_items', ['product_key' => $key]); $q->orWhereJsonContains('line_items', ['product_key' => $key]);
} }
}); });
} }
return $query; return $query;
@ -121,7 +122,7 @@ class ProductSalesExport extends BaseExport
//insert the header //insert the header
$query = Invoice::query() $query = Invoice::query()
->withTrashed() ->withTrashed()
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id) ->where('company_id', $this->company->id)
@ -138,30 +139,29 @@ class ProductSalesExport extends BaseExport
$product_keys = &$this->input['product_key']; $product_keys = &$this->input['product_key'];
if($product_keys){ if($product_keys) {
$product_keys = explode(",", $product_keys); $product_keys = explode(",", $product_keys);
} }
$query->cursor() $query->cursor()
->each(function ($invoice) use($product_keys) { ->each(function ($invoice) use ($product_keys) {
foreach ($invoice->line_items as $item) { foreach ($invoice->line_items as $item) {
if($product_keys) if($product_keys) {
{ if(in_array($item->product_key, $product_keys)) {
if(in_array($item->product_key, $product_keys)) $this->csv->insertOne($this->buildRow($invoice, $item));
$this->csv->insertOne($this->buildRow($invoice, $item)); }
} } else {
else { $this->csv->insertOne($this->buildRow($invoice, $item));
$this->csv->insertOne($this->buildRow($invoice, $item)); }
}
} }
}); });
$grouped = $this->sales->groupBy('product_key')->map(function ($key, $value) use($product_keys){ $grouped = $this->sales->groupBy('product_key')->map(function ($key, $value) use ($product_keys) {
if($product_keys && !in_array($value, $product_keys)){ if($product_keys && !in_array($value, $product_keys)) {
return false; return false;
} }
@ -185,7 +185,8 @@ class ProductSalesExport extends BaseExport
})->reject(function ($value) { })->reject(function ($value) {
return $value === false; return $value === false;
});; });
;
$this->csv->insertOne([]); $this->csv->insertOne([]);
$this->csv->insertOne([]); $this->csv->insertOne([]);
@ -327,10 +328,10 @@ class ProductSalesExport extends BaseExport
* getProduct * getProduct
* *
* @param string $product_key * @param string $product_key
* @return Product * @return ?\Illuminate\Database\Eloquent\Model
*/ */
private function getProduct(string $product_key): ?Product // private function getProduct(string $product_key)
{ // {
return $this->products->firstWhere('product_key', $product_key); // return $this->products->firstWhere('product_key', $product_key);
} // }
} }

View File

@ -58,12 +58,12 @@ class PurchaseOrderExport extends BaseExport
$query = PurchaseOrder::query() $query = PurchaseOrder::query()
->withTrashed() ->withTrashed()
->with('vendor') ->with('vendor')
->whereHas('vendor', function ($q){ ->whereHas('vendor', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }
@ -72,8 +72,9 @@ class PurchaseOrderExport extends BaseExport
$clients = &$this->input['client_id']; $clients = &$this->input['client_id'];
if($clients) if($clients) {
$query = $this->addClientFilter($query, $clients); $query = $this->addClientFilter($query, $clients);
}
$query = $this->addPurchaseOrderStatusFilter($query, $this->input['status'] ?? ''); $query = $this->addPurchaseOrderStatusFilter($query, $this->input['status'] ?? '');

View File

@ -62,12 +62,12 @@ class PurchaseOrderItemExport extends BaseExport
$query = PurchaseOrder::query() $query = PurchaseOrder::query()
->withTrashed() ->withTrashed()
->whereHas('vendor', function ($q){ ->whereHas('vendor', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->with('vendor')->where('company_id', $this->company->id); ->with('vendor')->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }

View File

@ -31,11 +31,11 @@ class QuoteExport extends BaseExport
private Decorator $decorator; private Decorator $decorator;
private array $decorate_keys = [ // private array $decorate_keys = [
'client', // 'client',
'currency', // 'currency',
'invoice', // 'invoice',
]; // ];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
{ {
@ -64,12 +64,12 @@ class QuoteExport extends BaseExport
$query = Quote::query() $query = Quote::query()
->withTrashed() ->withTrashed()
->with('client') ->with('client')
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }

View File

@ -65,12 +65,12 @@ class QuoteItemExport extends BaseExport
$query = Quote::query() $query = Quote::query()
->withTrashed() ->withTrashed()
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->with('client')->where('company_id', $this->company->id); ->with('client')->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }

View File

@ -56,12 +56,12 @@ class RecurringInvoiceExport extends BaseExport
$query = RecurringInvoice::query() $query = RecurringInvoice::query()
->withTrashed() ->withTrashed()
->with('client') ->with('client')
->whereHas('client', function ($q){ ->whereHas('client', function ($q) {
$q->where('is_deleted', false); $q->where('is_deleted', false);
}) })
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }

View File

@ -31,7 +31,7 @@ class TaskExport extends BaseExport
public string $date_key = 'created_at'; public string $date_key = 'created_at';
private string $date_format = 'YYYY-MM-DD'; private string $date_format = 'Y-m-d';
public Writer $csv; public Writer $csv;
@ -69,22 +69,24 @@ class TaskExport extends BaseExport
$query = Task::query() $query = Task::query()
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
$clients = &$this->input['client_id']; $clients = &$this->input['client_id'];
if($clients) if($clients) {
$query = $this->addClientFilter($query, $clients); $query = $this->addClientFilter($query, $clients);
}
$document_attachments = &$this->input['document_email_attachment']; $document_attachments = &$this->input['document_email_attachment'];
if($document_attachments) if($document_attachments) {
$this->queueDocuments($query); $this->queueDocuments($query);
}
return $query; return $query;
@ -178,13 +180,7 @@ class TaskExport extends BaseExport
$logs = json_decode($task->time_log, 1); $logs = json_decode($task->time_log, 1);
$date_format_default = 'Y-m-d'; $date_format_default = $this->date_format;
$date_format = DateFormat::find($task->company->settings->date_format_id);
if ($date_format) {
$date_format_default = $date_format->format;
}
foreach ($logs as $key => $item) { foreach ($logs as $key => $item) {
if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) { if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) {
@ -224,7 +220,7 @@ class TaskExport extends BaseExport
} }
} }
/** /**
* Add Task Status Filter * Add Task Status Filter
* *
@ -234,7 +230,7 @@ class TaskExport extends BaseExport
*/ */
protected function addTaskStatusFilter(Builder $query, string $status): Builder protected function addTaskStatusFilter(Builder $query, string $status): Builder
{ {
/** @var array $status_parameters */
$status_parameters = explode(',', $status); $status_parameters = explode(',', $status);
if (in_array('all', $status_parameters) || count($status_parameters) == 0) { if (in_array('all', $status_parameters) || count($status_parameters) == 0) {

View File

@ -63,8 +63,8 @@ class VendorExport extends BaseExport
$query = Vendor::query()->with('contacts') $query = Vendor::query()->with('contacts')
->withTrashed() ->withTrashed()
->where('company_id', $this->company->id); ->where('company_id', $this->company->id);
if(!$this->input['include_deleted'] ?? false){ if(!$this->input['include_deleted'] ?? false) {
$query->where('is_deleted', 0); $query->where('is_deleted', 0);
} }
@ -171,16 +171,16 @@ class VendorExport extends BaseExport
return $entity; return $entity;
} }
private function calculateStatus($vendor) // private function calculateStatus($vendor)
{ // {
if ($vendor->is_deleted) { // if ($vendor->is_deleted) {
return ctrans('texts.deleted'); // return ctrans('texts.deleted');
} // }
if ($vendor->deleted_at) { // if ($vendor->deleted_at) {
return ctrans('texts.archived'); // return ctrans('texts.archived');
} // }
return ctrans('texts.active'); // return ctrans('texts.active');
} // }
} }

View File

@ -25,7 +25,7 @@ class ContactDecorator implements DecoratorInterface
$contact = $entity->contacts()->first(); $contact = $entity->contacts()->first();
} elseif($entity->client) { } elseif($entity->client) {
$contact = $entity->client->primary_contact->first() ?? $entity->client->contacts()->whereNotNull('email')->first(); $contact = $entity->client->primary_contact->first() ?? $entity->client->contacts()->whereNotNull('email')->first();
} elseif($entity->vendor) { } elseif($entity->vendor) {
$contact = $entity->vendor->primary_contact->first() ?? $entity->vendor->contacts()->whereNotNull('email')->first(); $contact = $entity->vendor->primary_contact->first() ?? $entity->vendor->contacts()->whereNotNull('email')->first();
} }

View File

@ -23,14 +23,13 @@ class BankIntegrationFactory
$bank_integration->company_id = $company_id; $bank_integration->company_id = $company_id;
$bank_integration->provider_name = ''; $bank_integration->provider_name = '';
$bank_integration->bank_account_id = '';
$bank_integration->bank_account_name = ''; $bank_integration->bank_account_name = '';
$bank_integration->bank_account_number = ''; $bank_integration->bank_account_number = '';
$bank_integration->bank_account_status = ''; $bank_integration->bank_account_status = '';
$bank_integration->bank_account_type = ''; $bank_integration->bank_account_type = '';
$bank_integration->balance = 0; $bank_integration->balance = 0;
$bank_integration->currency = ''; $bank_integration->currency = '';
$bank_integration->auto_sync = 1; $bank_integration->auto_sync = true;
return $bank_integration; return $bank_integration;
} }

View File

@ -29,7 +29,7 @@ class ClientFactory
$client->balance = 0; $client->balance = 0;
$client->paid_to_date = 0; $client->paid_to_date = 0;
$client->country_id = null; $client->country_id = null;
$client->is_deleted = 0; $client->is_deleted = false;
$client->client_hash = Str::random(40); $client->client_hash = Str::random(40);
$client->settings = ClientSettings::defaults(); $client->settings = ClientSettings::defaults();
$client->classification = ''; $client->classification = '';

View File

@ -33,7 +33,7 @@ class CloneQuoteToProjectFactory
$project->custom_value2 = ''; $project->custom_value2 = '';
$project->custom_value3 = ''; $project->custom_value3 = '';
$project->custom_value4 = ''; $project->custom_value4 = '';
$project->is_deleted = 0; $project->is_deleted = false;
return $project; return $project;
} }

View File

@ -48,7 +48,7 @@ class CompanyFactory
$company->markdown_email_enabled = true; $company->markdown_email_enabled = true;
$company->markdown_enabled = false; $company->markdown_enabled = false;
$company->tax_data = new TaxModel(); $company->tax_data = new TaxModel();
$company->first_month_of_year = 1; $company->first_month_of_year = '1';
$company->smtp_encryption = 'tls'; $company->smtp_encryption = 'tls';
$company->smtp_host = ''; $company->smtp_host = '';
$company->smtp_local_domain = ''; $company->smtp_local_domain = '';
@ -56,7 +56,7 @@ class CompanyFactory
$company->smtp_port = ''; $company->smtp_port = '';
$company->smtp_username = ''; $company->smtp_username = '';
$company->smtp_verify_peer = true; $company->smtp_verify_peer = true;
return $company; return $company;
} }
} }

View File

@ -24,7 +24,7 @@ class CompanyGatewayFactory
$company_gateway->require_shipping_address = false; $company_gateway->require_shipping_address = false;
$company_gateway->config = encrypt(json_encode(new \stdClass())); $company_gateway->config = encrypt(json_encode(new \stdClass()));
$company_gateway->always_show_required_fields = true; $company_gateway->always_show_required_fields = true;
return $company_gateway; return $company_gateway;
} }
} }

View File

@ -52,7 +52,7 @@ class PurchaseOrderFactory
$purchase_order->exchange_rate = 1; $purchase_order->exchange_rate = 1;
$purchase_order->total_taxes = 0; $purchase_order->total_taxes = 0;
$purchase_order->uses_inclusive_taxes = false; $purchase_order->uses_inclusive_taxes = false;
return $purchase_order; return $purchase_order;
} }
} }

View File

@ -82,11 +82,15 @@ class RecurringExpenseToExpenseFactory
} else { } else {
$locale = $recurring_expense->company->locale(); $locale = $recurring_expense->company->locale();
$date_formats = Cache::get('date_formats'); //@deprecated
// $date_formats = Cache::get('date_formats');
$date_format = $date_formats->filter(function ($item) use ($recurring_expense) { /** @var \Illuminate\Support\Collection<\App\Models\DateFormat> */
$date_formats = app('date_formats');
$date_format = $date_formats->first(function ($item) use ($recurring_expense) {
return $item->id == $recurring_expense->company->settings->date_format_id; return $item->id == $recurring_expense->company->settings->date_format_id;
})->first()->format; })->format;
} }
Carbon::setLocale($locale); Carbon::setLocale($locale);
@ -144,7 +148,7 @@ class RecurringExpenseToExpenseFactory
continue; continue;
} }
if (Str::contains($match, '|')) { // if (Str::contains($match, '|')) {
$parts = explode('|', $match); // [ '[MONTH', 'MONTH+2]' ] $parts = explode('|', $match); // [ '[MONTH', 'MONTH+2]' ]
$left = substr($parts[0], 1); // 'MONTH' $left = substr($parts[0], 1); // 'MONTH'
@ -182,7 +186,7 @@ class RecurringExpenseToExpenseFactory
$value, $value,
1 1
); );
} // }
} }
// Second case with more common calculations. // Second case with more common calculations.

View File

@ -23,7 +23,7 @@ class SubscriptionFactory
$billing_subscription->company_id = $company_id; $billing_subscription->company_id = $company_id;
$billing_subscription->user_id = $user_id; $billing_subscription->user_id = $user_id;
$billing_subscription->steps = collect(Purchase::defaultSteps()) $billing_subscription->steps = collect(Purchase::defaultSteps())
->map(fn($step) => StepService::mapClassNameToString($step)) ->map(fn ($step) => StepService::mapClassNameToString($step))
->implode(','); ->implode(',');
return $billing_subscription; return $billing_subscription;

View File

@ -20,7 +20,7 @@ class TaxRateFactory
$tax_rate = new TaxRate(); $tax_rate = new TaxRate();
$tax_rate->name = ''; $tax_rate->name = '';
$tax_rate->rate = ''; $tax_rate->rate = 0;
$tax_rate->company_id = $company_id; $tax_rate->company_id = $company_id;
$tax_rate->user_id = $user_id; $tax_rate->user_id = $user_id;

View File

@ -26,7 +26,7 @@ class VendorFactory
$vendor->private_notes = ''; $vendor->private_notes = '';
$vendor->public_notes = ''; $vendor->public_notes = '';
$vendor->country_id = 4; $vendor->country_id = 4;
$vendor->is_deleted = 0; $vendor->is_deleted = false;
$vendor->vendor_hash = Str::random(40); $vendor->vendor_hash = Str::random(40);
// $vendor->classification = ''; // $vendor->classification = '';

View File

@ -115,6 +115,29 @@ class BankTransactionFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
/**
* Filters the list based on Bank Accounts.
*
* @param string $ids Comma Separated List of bank account ids
* @return Builder
*/
public function bank_integration_ids(string $ids = ''): Builder
{
if(strlen($ids) == 0) {
return $this->builder;
}
$ids = $this->transformKeys(explode(",", $ids));
$this->builder->where(function ($query) use ($ids) {
$query->whereIn('bank_integration_id', $ids);
});
return $this->builder;
}
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.
* *

View File

@ -160,8 +160,9 @@ class ClientFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
if($sort_col[0] == 'documents') if($sort_col[0] == 'documents') {
return $this->builder; return $this->builder;
}
if ($sort_col[0] == 'display_name') { if ($sort_col[0] == 'display_name') {
$sort_col[0] = 'name'; $sort_col[0] = 'name';

View File

@ -58,10 +58,11 @@ class DesignFilters extends QueryFilters
public function entities(string $entities = ''): Builder public function entities(string $entities = ''): Builder
{ {
if(stripos($entities, 'statement') !== false) if(stripos($entities, 'statement') !== false) {
$entities = 'client'; $entities = 'client';
}
if (strlen($entities) == 0 || str_contains($entities, ',')) { if (strlen($entities) == 0 || str_contains($entities, ',')) {
return $this->builder; return $this->builder;
} }

View File

@ -49,22 +49,22 @@ class DocumentFilters extends QueryFilters
*/ */
public function client_id(string $client_id = ''): Builder public function client_id(string $client_id = ''): Builder
{ {
return $this->builder->where(function ($query) use ($client_id) { return $this->builder->where(function ($query) use ($client_id) {
$query->whereHasMorph('documentable', [ $query->whereHasMorph('documentable', [
\App\Models\Invoice::class, \App\Models\Invoice::class,
\App\Models\Quote::class, \App\Models\Quote::class,
\App\Models\Credit::class, \App\Models\Credit::class,
\App\Models\Expense::class, \App\Models\Expense::class,
\App\Models\Payment::class, \App\Models\Payment::class,
\App\Models\Task::class, \App\Models\Task::class,
\App\Models\RecurringExpense::class, \App\Models\RecurringExpense::class,
\App\Models\RecurringInvoice::class, \App\Models\RecurringInvoice::class,
\App\Models\Project::class, \App\Models\Project::class,
], function ($q2) use ($client_id) { ], function ($q2) use ($client_id) {
$q2->where('client_id', $this->decodePrimaryKey($client_id)); $q2->where('client_id', $this->decodePrimaryKey($client_id));
})->orWhereHasMorph('documentable', [\App\Models\Client::class], function ($q3) use ($client_id) { })->orWhereHasMorph('documentable', [\App\Models\Client::class], function ($q3) use ($client_id) {
$q3->where('id', $this->decodePrimaryKey($client_id)); $q3->where('id', $this->decodePrimaryKey($client_id));
}); });
}); });
@ -74,8 +74,7 @@ class DocumentFilters extends QueryFilters
{ {
$types = explode(',', $types); $types = explode(',', $types);
foreach ($types as $type) foreach ($types as $type) {
{
match($type) { match($type) {
'private' => $this->builder->where('is_public', 0), 'private' => $this->builder->where('is_public', 0),
'public' => $this->builder->where('is_public', 1), 'public' => $this->builder->where('is_public', 1),
@ -87,7 +86,7 @@ class DocumentFilters extends QueryFilters
} }
return $this->builder; return $this->builder;
} }
/** /**
* Sorts the list based on $sort. * Sorts the list based on $sort.

View File

@ -79,7 +79,7 @@ class ExpenseFilters extends QueryFilters
$this->builder->where(function ($query) use ($status_parameters) { $this->builder->where(function ($query) use ($status_parameters) {
if (in_array('logged', $status_parameters)) { if (in_array('logged', $status_parameters)) {
$query->orWhere(function ($query) { $query->orWhere(function ($query) {
$query->where('amount', '>', 0) $query->where('amount', '>=', 0)
->whereNull('invoice_id') ->whereNull('invoice_id')
->whereNull('payment_date') ->whereNull('payment_date')
->where('should_be_invoiced', false); ->where('should_be_invoiced', false);
@ -111,8 +111,8 @@ class ExpenseFilters extends QueryFilters
}); });
} }
if(in_array('uncategorized', $status_parameters)){ if(in_array('uncategorized', $status_parameters)) {
$query->orWhere(function ($query){ $query->orWhere(function ($query) {
$query->whereNull('category_id'); $query->whereNull('category_id');
}); });
} }

View File

@ -228,10 +228,9 @@ class InvoiceFilters extends QueryFilters
$date = Carbon::createFromTimestamp((int)$date); $date = Carbon::createFromTimestamp((int)$date);
} else { } else {
try{ try {
$date = Carbon::parse($date); $date = Carbon::parse($date);
} } catch(\Exception $e) {
catch(\Exception $e){
return $this->builder; return $this->builder;
} }
} }
@ -272,6 +271,7 @@ class InvoiceFilters extends QueryFilters
if (count($parts) != 2) { if (count($parts) != 2) {
return $this->builder; return $this->builder;
} }
try { try {
$start_date = Carbon::parse($parts[0]); $start_date = Carbon::parse($parts[0]);
@ -282,7 +282,6 @@ class InvoiceFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
return $this->builder;
} }
/** /**
@ -308,7 +307,6 @@ class InvoiceFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
return $this->builder;
} }
@ -339,7 +337,7 @@ class InvoiceFilters extends QueryFilters
// return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir); // return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir);
// return $this->builder->orderByRaw("number REGEXP '^[A-Za-z]+$',CAST(number as SIGNED INTEGER),CAST(REPLACE(number,'-','')AS SIGNED INTEGER) ,number"); // return $this->builder->orderByRaw("number REGEXP '^[A-Za-z]+$',CAST(number as SIGNED INTEGER),CAST(REPLACE(number,'-','')AS SIGNED INTEGER) ,number");
// return $this->builder->orderByRaw('ABS(number) ' . $dir); // return $this->builder->orderByRaw('ABS(number) ' . $dir);
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir); return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
} }
return $this->builder->orderBy($sort_col[0], $dir); return $this->builder->orderBy($sort_col[0], $dir);

View File

@ -204,7 +204,6 @@ class PaymentFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
return $this->builder;
} }
/** /**

View File

@ -133,7 +133,7 @@ class RecurringInvoiceFilters extends QueryFilters
return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir); return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir);
} }
if($sort_col[0] == 'next_send_datetime'){ if($sort_col[0] == 'next_send_datetime') {
$sort_col[0] = 'next_send_date'; $sort_col[0] = 'next_send_date';
} }
@ -162,9 +162,10 @@ class RecurringInvoiceFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
/** @var array $key_parameters */
$key_parameters = explode(',', $value); $key_parameters = explode(',', $value);
if (count($key_parameters)) { if (count($key_parameters) > 0) {
return $this->builder->where(function ($query) use ($key_parameters) { return $this->builder->where(function ($query) use ($key_parameters) {
foreach ($key_parameters as $key) { foreach ($key_parameters as $key) {
$query->orWhereJsonContains('line_items', ['product_key' => $key]); $query->orWhereJsonContains('line_items', ['product_key' => $key]);
@ -183,6 +184,7 @@ class RecurringInvoiceFilters extends QueryFilters
*/ */
public function next_send_between(string $range = ''): Builder public function next_send_between(string $range = ''): Builder
{ {
/** @var array $parts */
$parts = explode('|', $range); $parts = explode('|', $range);
if (!isset($parts[0]) || !isset($parts[1])) { if (!isset($parts[0]) || !isset($parts[1])) {

View File

@ -88,7 +88,7 @@ class TaskFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
public function project_tasks($project): Builder public function project_tasks(string $project = ''): Builder
{ {
if (strlen($project) == 0) { if (strlen($project) == 0) {
return $this->builder; return $this->builder;
@ -175,6 +175,7 @@ class TaskFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
/** @var array $status_parameters */
$status_parameters = explode(',', $value); $status_parameters = explode(',', $value);
if(count($status_parameters) >= 1) { if(count($status_parameters) >= 1) {

View File

@ -24,9 +24,10 @@ use App\Services\Email\Email;
use App\Models\BankIntegration; use App\Models\BankIntegration;
use App\Services\Email\EmailObject; use App\Services\Email\EmailObject;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Mail\Mailables\Address;
use App\Helpers\Bank\Nordigen\Transformer\AccountTransformer; use App\Helpers\Bank\Nordigen\Transformer\AccountTransformer;
use App\Helpers\Bank\Nordigen\Transformer\TransactionTransformer; use App\Helpers\Bank\Nordigen\Transformer\TransactionTransformer;
use Illuminate\Mail\Mailables\Address;
class Nordigen class Nordigen
{ {
@ -99,7 +100,7 @@ class Nordigen
} catch (\Exception $e) { } catch (\Exception $e) {
nlog("Nordigen getAccount() failed => {$account_id} => " . $e->getMessage()); nlog("Nordigen getAccount() failed => {$account_id} => " . $e->getMessage());
return false; return false;
} }
@ -149,6 +150,11 @@ class Nordigen
public function disabledAccountEmail(BankIntegration $bank_integration): void public function disabledAccountEmail(BankIntegration $bank_integration): void
{ {
$cache_key = "email_quota:{$bank_integration->company->company_key}:{$bank_integration->id}";
if(Cache::has($cache_key)) {
return;
}
App::setLocale($bank_integration->company->getLocale()); App::setLocale($bank_integration->company->getLocale());
@ -164,6 +170,7 @@ class Nordigen
Email::dispatch($mo, $bank_integration->company); Email::dispatch($mo, $bank_integration->company);
Cache::put($cache_key, true, 60 * 60 * 24);
} }

View File

@ -71,7 +71,7 @@ class TransactionTransformer implements BankRevenueInterface
private Company $company; private Company $company;
function __construct(Company $company) public function __construct(Company $company)
{ {
$this->company = $company; $this->company = $company;
} }
@ -156,22 +156,16 @@ class TransactionTransformer implements BankRevenueInterface
private function convertCurrency(string $code) private function convertCurrency(string $code)
{ {
$currencies = Cache::get('currencies'); $currencies = app('currencies');
if (!$currencies) { $currency = $currencies->first(function ($item) use ($code) {
$this->buildCache(true); /** @var \App\Models\Currency $item */
}
$currency = $currencies->filter(function ($item) use ($code) {
return $item->code == $code; return $item->code == $code;
})->first(); });
if ($currency) {
return $currency->id;
}
return 1;
/** @var \App\Models\Currency $currency */
return $currency ? $currency->id : 1; //@phpstan-ignore-line
} }
private function formatDate(string $input) private function formatDate(string $input)
@ -192,7 +186,7 @@ class TransactionTransformer implements BankRevenueInterface
} }
try { try {
return Carbon::createFromFormat("d-m-Y", $input)->setTimezone($timezone_name)->format($date_format_default) ?? $input; return Carbon::createFromFormat("d-m-Y", $input)->setTimezone($timezone_name)->format($date_format_default) ?? $input;
} catch (\Exception $e) { } catch (\Exception $e) {
return $input; return $input;
} }

View File

@ -1,111 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Helpers\Bank\Yodlee\DTO;
use Illuminate\Support\Collection;
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Data;
/**
* @deprecated
* [
"account": [
[
"CONTAINER": "bank",
"providerAccountId": 1005,
"accountName": "Business Acct",
"accountStatus": "ACTIVE",
"accountNumber": "1011",
"aggregationSource": "USER",
"isAsset": true,
"balance": [
"currency": "AUD",
"amount": 304.98,
],
"id": 10139315,
"includeInNetWorth": true,
"providerId": "3857",
"providerName": "Bank",
"isManual": false,
"availableBalance": {#2966
"currency": "AUD",
"amount": 304.98,
],
"currentBalance": [
"currency": "AUD",
"amount": 3044.98,
],
"accountType": "CHECKING",
"displayedName": "after David",
"createdDate": "2023-01-10T08:29:07Z",
"classification": "SMALL_BUSINESS",
"lastUpdated": "2023-08-01T23:50:13Z",
"nickname": "Business ",
"bankTransferCode": [
[
"id": "062",
"type": "BSB",
],
],
"dataset": [
[
"name": "BASIC_AGG_DATA",
"additionalStatus": "AVAILABLE_DATA_RETRIEVED",
"updateEligibility": "ALLOW_UPDATE",
"lastUpdated": "2023-08-01T23:49:53Z",
"lastUpdateAttempt": "2023-08-01T23:49:53Z",
"nextUpdateScheduled": "2023-08-03T14:45:14Z",
],
],
],
],
];
*/
class AccountSummary extends Data
{
public ?int $id;
#[MapInputName('CONTAINER')]
public ?string $account_type = '';
#[MapInputName('accountName')]
public ?string $account_name = '';
#[MapInputName('accountStatus')]
public ?string $account_status = '';
#[MapInputName('accountNumber')]
public ?string $account_number = '';
#[MapInputName('providerAccountId')]
public int $provider_account_id;
#[MapInputName('providerId')]
public ?string $provider_id = '';
#[MapInputName('providerName')]
public ?string $provider_name = '';
public ?string $nickname = '';
public ?float $current_balance = 0;
public ?string $account_currency = '';
public static function prepareForPipeline(Collection $properties): Collection
{
$properties->put('current_balance', $properties['currentBalance']['amount'] ?? 0);
$properties->put('account_currency', $properties['currentBalance']['currency'] ?? 0);
return $properties;
}
}

View File

@ -171,20 +171,16 @@ class IncomeTransformer implements BankRevenueInterface
private function convertCurrency(string $code) private function convertCurrency(string $code)
{ {
$currencies = Cache::get('currencies');
if (! $currencies) { $currencies = app('currencies');
$this->buildCache(true);
}
$currency = $currencies->filter(function ($item) use ($code) { $currency = $currencies->first(function ($item) use ($code) {
/** @var \App\Models\Currency $item */
return $item->code == $code; return $item->code == $code;
})->first(); });
if ($currency) { /** @var \App\Models\Currency $currency */
return $currency->id; return $currency ? $currency->id : 1; //@phpstan-ignore-line
}
return 1;
} }
} }

View File

@ -26,15 +26,15 @@ use BaconQrCode\Writer;
*/ */
class EpcQrGenerator class EpcQrGenerator
{ {
private array $sepa = [ // private array $sepa = [
'serviceTag' => 'BCD', // 'serviceTag' => 'BCD',
'version' => 2, // 'version' => 2,
'characterSet' => 1, // 'characterSet' => 1,
'identification' => 'SCT', // 'identification' => 'SCT',
'bic' => '', // 'bic' => '',
'purpose' => '', // 'purpose' => '',
]; // ];
public function __construct(protected Company $company, protected Invoice|RecurringInvoice $invoice, protected float $amount) public function __construct(protected Company $company, protected Invoice|RecurringInvoice $invoice, protected float $amount)
{ {
@ -59,36 +59,47 @@ class EpcQrGenerator
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>"; <rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
} catch(\Throwable $e) { } catch(\Throwable $e) {
// nlog("EPC QR failure => ".$e->getMessage()); nlog("EPC QR failure => ".$e->getMessage());
return ''; return '';
} catch(\Exception $e) { }
// nlog("EPC QR failure => ".$e->getMessage());
return '';
} catch(InvalidArgumentException $e) {
// nlog("EPC QR failure => ".$e->getMessage());
return '';
}
} }
public function encodeMessage() public function encodeMessage()
{ {
return rtrim(implode("\n", [ // return rtrim(implode("\n", [
$this->sepa['serviceTag'], // $this->sepa['serviceTag'],
sprintf('%03d', $this->sepa['version']), // sprintf('%03d', $this->sepa['version']),
$this->sepa['characterSet'], // $this->sepa['characterSet'],
$this->sepa['identification'], // $this->sepa['identification'],
isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '', // isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '',
$this->company->present()->name(), // $this->company->present()->name(),
isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '', // isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '',
$this->formatMoney($this->amount), // $this->formatMoney($this->amount),
$this->sepa['purpose'], // $this->sepa['purpose'],
substr($this->invoice->number, 0, 34), // substr($this->invoice->number, 0, 34),
'', // '',
' ' // ' '
]), "\n"); // ]), "\n");
$data = [
'BCD',
'002', // Version
'1', // Encoding: 1 = UTF-8
'SCT', // Service Tag: SEPA Credit Transfer
isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '', // BIC
$this->company->present()->name(), // Name of the beneficiary
isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '', // IBAN
$this->formatMoney($this->amount), // Amount with EUR prefix
'', // Reference
substr($this->invoice->number, 0, 34) // Unstructured remittance information
];
return implode("\n", $data);
} }
// substr("{$this->invoice->number} {$this->invoice->client->number}", 0,139), // substr("{$this->invoice->number} {$this->invoice->client->number}", 0,139),

View File

@ -27,7 +27,7 @@ trait CustomValuer
public function valuerTax($custom_value, $has_custom_invoice_taxes) public function valuerTax($custom_value, $has_custom_invoice_taxes)
{ {
if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) { if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) {
return round($custom_value * ($this->invoice->tax_rate1 / 100), 2) + round($custom_value * ($this->invoice->tax_rate2 / 100), 2) + round($custom_value * ($this->invoice->tax_rate3 / 100), 2); return round($custom_value * ($this->invoice->tax_rate1 / 100), 2) + round($custom_value * ($this->invoice->tax_rate2 / 100), 2) + round($custom_value * ($this->invoice->tax_rate3 / 100), 2);
} }
@ -35,17 +35,18 @@ trait CustomValuer
return 0; return 0;
} }
public function multiInclusiveTax($custom_value, $has_custom_invoice_taxes) { public function multiInclusiveTax($custom_value, $has_custom_invoice_taxes)
{
if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) { if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) {
$tax = 0; $tax = 0;
$tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate1 / 100))), 2); $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate1 / 100))), 2);
$tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate2 / 100))), 2); $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate2 / 100))), 2);
$tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate3 / 100))), 2); $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate3 / 100))), 2);
return round($tax,2); return round($tax, 2);
} }
return 0; return 0;

View File

@ -29,6 +29,7 @@ class InvoiceItemSum
use Discounter; use Discounter;
use Taxer; use Taxer;
//@phpstan-ignore-next-line
private array $eu_tax_jurisdictions = [ private array $eu_tax_jurisdictions = [
'AT', // Austria 'AT', // Austria
'BE', // Belgium 'BE', // Belgium
@ -170,7 +171,7 @@ class InvoiceItemSum
private function shouldCalculateTax(): self private function shouldCalculateTax(): self
{ {
if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) { if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) { //@phpstan-ignore-line
$this->calc_tax = false; $this->calc_tax = false;
return $this; return $this;
} }
@ -182,7 +183,7 @@ class InvoiceItemSum
$class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule"; $class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule";
$this->rule = new $class(); $this->rule = new $class();
if($this->rule->regionWithNoTaxCoverage($this->client->country->iso_3166_2)) { if($this->rule->regionWithNoTaxCoverage($this->client->country->iso_3166_2)) {
return $this; return $this;
} }

View File

@ -27,7 +27,7 @@ class InvoiceItemSumInclusive
use Discounter; use Discounter;
use Taxer; use Taxer;
//@phpstan-ignore-next-line
private array $eu_tax_jurisdictions = [ private array $eu_tax_jurisdictions = [
'AT', // Austria 'AT', // Austria
'BE', // Belgium 'BE', // Belgium
@ -98,6 +98,7 @@ class InvoiceItemSumInclusive
private $total_taxes; private $total_taxes;
/** @phpstan-ignore-next-line */
private $item; private $item;
private $line_items; private $line_items;
@ -399,7 +400,7 @@ class InvoiceItemSumInclusive
private function shouldCalculateTax(): self private function shouldCalculateTax(): self
{ {
if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) { if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) {//@phpstan-ignore-line
$this->calc_tax = false; $this->calc_tax = false;
return $this; return $this;
} }

View File

@ -229,7 +229,7 @@ class InvoiceSum
{ {
// $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision); // $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
// $this->invoice->total_taxes = $this->getTotalTaxes(); // $this->invoice->total_taxes = $this->getTotalTaxes();
$this->setCalculatedAttributes(); $this->setCalculatedAttributes();
$this->invoice->balance = $this->invoice->amount; $this->invoice->balance = $this->invoice->amount;
$this->invoice->saveQuietly(); $this->invoice->saveQuietly();
@ -245,10 +245,9 @@ class InvoiceSum
*/ */
private function setCalculatedAttributes(): self private function setCalculatedAttributes(): self
{ {
if($this->invoice->status_id == Invoice::STATUS_CANCELLED){ if($this->invoice->status_id == Invoice::STATUS_CANCELLED) {
$this->invoice->balance = 0; $this->invoice->balance = 0;
} } elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) {
elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) {
if ($this->invoice->amount != $this->invoice->balance) { if ($this->invoice->amount != $this->invoice->balance) {
$this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date; //21-02-2024 cannot use the calculated $paid_to_date here as it could send the balance backward. $this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date; //21-02-2024 cannot use the calculated $paid_to_date here as it could send the balance backward.
} else { } else {
@ -258,7 +257,7 @@ class InvoiceSum
/* Set new calculated total */ /* Set new calculated total */
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision); $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
if($this->rappen_rounding){ if($this->rappen_rounding) {
$this->invoice->amount = $this->roundRappen($this->invoice->amount); $this->invoice->amount = $this->roundRappen($this->invoice->amount);
$this->invoice->balance = $this->roundRappen($this->invoice->balance); $this->invoice->balance = $this->roundRappen($this->invoice->balance);
} }
@ -269,7 +268,7 @@ class InvoiceSum
} }
function roundRappen($value): float public function roundRappen($value): float
{ {
return round($value / .05, 0) * .05; return round($value / .05, 0) * .05;
} }

View File

@ -171,7 +171,7 @@ class InvoiceSumInclusive
$this->total_taxes += $tax; $this->total_taxes += $tax;
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.floatval($this->invoice->tax_rate3).'%', 'total' => $tax]; $this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.floatval($this->invoice->tax_rate3).'%', 'total' => $tax];
} }
return $this; return $this;
} }
@ -279,10 +279,9 @@ class InvoiceSumInclusive
private function setCalculatedAttributes() private function setCalculatedAttributes()
{ {
/* If amount != balance then some money has been paid on the invoice, need to subtract this difference from the total to set the new balance */ /* If amount != balance then some money has been paid on the invoice, need to subtract this difference from the total to set the new balance */
if($this->invoice->status_id == Invoice::STATUS_CANCELLED){ if($this->invoice->status_id == Invoice::STATUS_CANCELLED) {
$this->invoice->balance = 0; $this->invoice->balance = 0;
} } elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) {
elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) {
if ($this->invoice->amount != $this->invoice->balance) { if ($this->invoice->amount != $this->invoice->balance) {
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date; $this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date;
} else { } else {
@ -302,8 +301,8 @@ class InvoiceSumInclusive
return $this; return $this;
} }
function roundRappen($value): float public function roundRappen($value): float
{ {
return round($value / .05, 0) * .05; return round($value / .05, 0) * .05;
} }
@ -373,7 +372,7 @@ class InvoiceSumInclusive
$this->total_taxes += $total_line_tax; $this->total_taxes += $total_line_tax;
} }
return $this; return $this;
} }

View File

@ -58,12 +58,12 @@ class ProRata
* Prepares the line items of an invoice * Prepares the line items of an invoice
* to be pro rata refunded. * to be pro rata refunded.
* *
* @param Invoice $invoice * @param ?Invoice $invoice
* @param bool $is_credit * @param bool $is_credit
* @return array * @return array
* @throws Exception * @throws Exception
*/ */
public function refundItems(Invoice $invoice, $is_credit = false): array public function refundItems(?Invoice $invoice, $is_credit = false): array
{ {
if (! $invoice) { if (! $invoice) {
return []; return [];

View File

@ -34,7 +34,7 @@ class GmailTransport extends AbstractTransport
$message = MessageConverter::toEmail($message->getOriginalMessage()); $message = MessageConverter::toEmail($message->getOriginalMessage());
/** @phpstan-ignore-next-line **/ /** @phpstan-ignore-next-line **/
$token = $message->getHeaders()->get('gmailtoken')->getValue(); $token = $message->getHeaders()->get('gmailtoken')->getValue(); // @phpstan-ignore-line
$message->getHeaders()->remove('gmailtoken'); $message->getHeaders()->remove('gmailtoken');
$client = new Client(); $client = new Client();
@ -53,9 +53,8 @@ class GmailTransport extends AbstractTransport
if ($bccs) { if ($bccs) {
$bcc_list = 'Bcc: '; $bcc_list = 'Bcc: ';
foreach ($bccs->getAddresses() as $address) {
/** @phpstan-ignore-next-line **/
foreach ($bccs->getAddresses() as $address) {
$bcc_list .= $address->getAddress() .','; $bcc_list .= $address->getAddress() .',';
} }
@ -65,18 +64,18 @@ class GmailTransport extends AbstractTransport
$body->setRaw($this->base64_encode($bcc_list.$message->toString())); $body->setRaw($this->base64_encode($bcc_list.$message->toString()));
// try { // try {
$service->users_messages->send('me', $body, []); $service->users_messages->send('me', $body, []);
// } catch(\Google\Service\Exception $e) { // } catch(\Google\Service\Exception $e) {
// /* Need to slow down */ // /* Need to slow down */
// if ($e->getCode() == '429') { // if ($e->getCode() == '429') {
// nlog("429 google - retrying "); // nlog("429 google - retrying ");
// sleep(rand(3,8)); // sleep(rand(3,8));
// try { // try {
// $service->users_messages->send('me', $body, []); // $service->users_messages->send('me', $body, []);
// } catch(\Google\Service\Exception $e) { // } catch(\Google\Service\Exception $e) {
// } // }
// } // }

View File

@ -54,17 +54,17 @@ class Office365MailTransport extends AbstractTransport
->setReturnType(\Microsoft\Graph\Model\Message::class) ->setReturnType(\Microsoft\Graph\Model\Message::class)
->execute(); ->execute();
} catch (\Exception $e) { } catch (\Exception $e) {
sleep(rand(5,10)); sleep(rand(5, 10));
try { try {
$graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail') $graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail')
->attachBody(base64_encode($bcc_list.$message->toString())) ->attachBody(base64_encode($bcc_list.$message->toString()))
->addHeaders(['Content-Type' => 'text/plain']) ->addHeaders(['Content-Type' => 'text/plain'])
->setReturnType(\Microsoft\Graph\Model\Message::class) ->setReturnType(\Microsoft\Graph\Model\Message::class)
->execute(); ->execute();
} catch (\Exception $e) { } catch (\Exception $e) {
} }
} }

View File

@ -61,7 +61,7 @@ class AccountController extends BaseController
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param CreateAccountRequest $request * @param CreateAccountRequest $request
* @return Response * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
*/ */
public function store(CreateAccountRequest $request) public function store(CreateAccountRequest $request)

View File

@ -105,6 +105,14 @@ class ActivityController extends BaseController
} }
/**
* downloadHistoricalEntity
*
* @param DownloadHistoricalEntityRequest $request
* @param Activity $activity
* @return \Symfony\Component\HttpFoundation\StreamedResponse | \Illuminate\Http\JsonResponse
*/
public function downloadHistoricalEntity(DownloadHistoricalEntityRequest $request, Activity $activity) public function downloadHistoricalEntity(DownloadHistoricalEntityRequest $request, Activity $activity)
{ {
$backup = $activity->backup; $backup = $activity->backup;

View File

@ -118,7 +118,7 @@ class ContactForgotPasswordController extends Controller
})->first(); })->first();
} }
$response = false; // $response = false;
if ($contact) { if ($contact) {
/* Update all instances of the client */ /* Update all instances of the client */
@ -131,16 +131,16 @@ class ContactForgotPasswordController extends Controller
} }
if ($request->ajax()) { if ($request->ajax()) {
if ($response == Password::RESET_THROTTLED) { if ($response == Password::RESET_THROTTLED) { // @phpstan-ignore-line
return response()->json(['message' => ctrans('passwords.throttled'), 'status' => false], 429); return response()->json(['message' => ctrans('passwords.throttled'), 'status' => false], 429);
} }
return $response == Password::RESET_LINK_SENT return $response == Password::RESET_LINK_SENT // @phpstan-ignore-line
? response()->json(['message' => 'Reset link sent to your email.', 'status' => true], 201) ? response()->json(['message' => 'Reset link sent to your email.', 'status' => true], 201)
: response()->json(['message' => 'Email not found', 'status' => false], 401); : response()->json(['message' => 'Email not found', 'status' => false], 401);
} }
return $response == Password::RESET_LINK_SENT return $response == Password::RESET_LINK_SENT // @phpstan-ignore-line
? $this->sendResetLinkResponse($request, $response) ? $this->sendResetLinkResponse($request, $response)
: $this->sendResetLinkFailedResponse($request, $response); : $this->sendResetLinkFailedResponse($request, $response);
} }

View File

@ -41,6 +41,9 @@ class ContactLoginController extends Controller
$company = false; $company = false;
$account = false; $account = false;
if($request->query('intended'))
$request->session()->put('url.intended', $request->query('intended'));
if ($request->session()->has('company_key')) { if ($request->session()->has('company_key')) {
MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key')); MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));
$company = Company::where('company_key', $request->session()->get('company_key'))->first(); $company = Company::where('company_key', $request->session()->get('company_key'))->first();
@ -52,7 +55,7 @@ class ContactLoginController extends Controller
$company = Company::where('company_key', $company_key)->first(); $company = Company::where('company_key', $company_key)->first();
} }
/** @var \App\Models\Company $company **/ /** @var ?\App\Models\Company $company **/
if ($company) { if ($company) {
$account = $company->account; $account = $company->account;
} elseif (! $company && strpos($request->getHost(), config('ninja.app_domain')) !== false) { } elseif (! $company && strpos($request->getHost(), config('ninja.app_domain')) !== false) {
@ -81,6 +84,7 @@ class ContactLoginController extends Controller
public function login(Request $request) public function login(Request $request)
{ {
Auth::shouldUse('contact'); Auth::shouldUse('contact');
if (Ninja::isHosted() && $request->has('company_key')) { if (Ninja::isHosted() && $request->has('company_key')) {
@ -125,6 +129,9 @@ class ContactLoginController extends Controller
protected function sendLoginResponse(Request $request) protected function sendLoginResponse(Request $request)
{ {
$intended = $request->session()->has('url.intended') ? $request->session()->get('url.intended') : false;
$request->session()->regenerate(); $request->session()->regenerate();
$this->clearLoginAttempts($request); $this->clearLoginAttempts($request);
@ -134,6 +141,9 @@ class ContactLoginController extends Controller
} }
$this->setRedirectPath(); $this->setRedirectPath();
if($intended)
$this->redirectTo = $intended;
return $request->wantsJson() return $request->wantsJson()
? new JsonResponse([], 204) ? new JsonResponse([], 204)
@ -146,8 +156,8 @@ class ContactLoginController extends Controller
event(new ContactLoggedIn($client, $client->company, Ninja::eventVars())); event(new ContactLoggedIn($client, $client->company, Ninja::eventVars()));
if (session()->get('url.intended')) { if ($request->session()->has('url.intended')) {
return redirect(session()->get('url.intended')); return redirect($request->session()->get('url.intended'));
} }
$this->setRedirectPath(); $this->setRedirectPath();
@ -165,19 +175,20 @@ class ContactLoginController extends Controller
private function setRedirectPath() private function setRedirectPath()
{ {
if (auth()->guard('contact')->user()->client->getSetting('enable_client_portal_dashboard') === true) { if (auth()->guard('contact')->user()->client->getSetting('enable_client_portal_dashboard') === true) {
$this->redirectTo = '/client/dashboard'; $this->redirectTo = '/client/dashboard';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES)) {
$this->redirectTo = '/client/invoices'; $this->redirectTo = '/client/invoices';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES)) {
$this->redirectTo = '/client/recurring_invoices'; $this->redirectTo = '/client/recurring_invoices';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES)) {
$this->redirectTo = '/client/quotes'; $this->redirectTo = '/client/quotes';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS)) {
$this->redirectTo = '/client/credits'; $this->redirectTo = '/client/credits';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_TASKS) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_TASKS)) {
$this->redirectTo = '/client/tasks'; $this->redirectTo = '/client/tasks';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_EXPENSES) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_EXPENSES)) {
$this->redirectTo = '/client/expenses'; $this->redirectTo = '/client/expenses';
} }
} }

View File

@ -50,7 +50,7 @@ class ContactRegisterController extends Controller
public function register(RegisterRequest $request) public function register(RegisterRequest $request)
{ {
$request->merge(['company' => $request->company()]); $request->merge(['company' => $request->company()]);
$service = new ClientRegisterService( $service = new ClientRegisterService(
company: $request->company(), company: $request->company(),
); );

View File

@ -46,7 +46,7 @@ class ForgotPasswordController extends Controller
/** /**
* @param Request $request * @param Request $request
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException * @throws \Illuminate\Validation\ValidationException
*/ */
public function sendResetLinkEmail(Request $request) public function sendResetLinkEmail(Request $request)

View File

@ -13,6 +13,7 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\DataMapper\Analytics\LoginFailure; use App\DataMapper\Analytics\LoginFailure;
use App\DataMapper\Analytics\LoginMeta;
use App\DataMapper\Analytics\LoginSuccess; use App\DataMapper\Analytics\LoginSuccess;
use App\Events\User\UserLoggedIn; use App\Events\User\UserLoggedIn;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
@ -111,6 +112,9 @@ class LoginController extends BaseController
->increment() ->increment()
->batch(); ->batch();
LightLogs::create(new LoginMeta($request->email, $request->ip, 'success'))
->batch();
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = $this->guard()->user(); $user = $this->guard()->user();
@ -159,6 +163,9 @@ class LoginController extends BaseController
->increment() ->increment()
->batch(); ->batch();
LightLogs::create(new LoginMeta($request->email, $request->ip, 'failure'))
->batch();
$this->incrementLoginAttempts($request); $this->incrementLoginAttempts($request);
return response() return response()
@ -172,7 +179,7 @@ class LoginController extends BaseController
* Refreshes the data feed with the current Company User. * Refreshes the data feed with the current Company User.
* *
* @param Request $request * @param Request $request
* @return Response|JsonResponse * @return \Illuminate\Http\Response|JsonResponse
*/ */
public function refresh(Request $request) public function refresh(Request $request)
{ {
@ -391,8 +398,8 @@ class LoginController extends BaseController
$truth->setCompany($set_company); $truth->setCompany($set_company);
//21-03-2024 //21-03-2024
$cu->each(function ($cu){ $cu->each(function ($cu) {
if(CompanyToken::where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()){ if(CompanyToken::where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()) {
(new CreateCompanyToken($cu->company, $cu->user, request()->server('HTTP_USER_AGENT')))->handle(); (new CreateCompanyToken($cu->company, $cu->user, request()->server('HTTP_USER_AGENT')))->handle();
} }
}); });
@ -481,7 +488,7 @@ class LoginController extends BaseController
* send login response to oauthed users * send login response to oauthed users
* *
* @param \App\Models\User $existing_user * @param \App\Models\User $existing_user
* @return Response | JsonResponse * @return Response| \Illuminate\Http\JsonResponse | JsonResponse
*/ */
private function existingOauthUser($existing_user) private function existingOauthUser($existing_user)
{ {
@ -651,7 +658,9 @@ class LoginController extends BaseController
} }
if(request()->hasHeader('X-REACT') || request()->query('react')) { if(request()->hasHeader('X-REACT') || request()->query('react')) {
Cache::put("react_redir:".auth()->user()?->account->key, 'true', 300); /**@var \App\Models\User $user */
$user = auth()->user();
Cache::put("react_redir:".$user?->account->key, 'true', 300);
} }
if (request()->has('code')) { if (request()->has('code')) {

View File

@ -78,7 +78,7 @@ class ResetPasswordController extends Controller
* Reset the given user's password. * Reset the given user's password.
* *
* @param Request $request * @param Request $request
* @return RedirectResponse|JsonResponse * @return \Illuminate\Http\RedirectResponse | \Illuminate\Http\RedirectResponse|JsonResponse
* @throws \Illuminate\Validation\ValidationException * @throws \Illuminate\Validation\ValidationException
*/ */
public function reset(Request $request) public function reset(Request $request)
@ -137,8 +137,8 @@ class ResetPasswordController extends Controller
return redirect('/#/login'); return redirect('/#/login');
} }
return redirect($this->redirectPath()) // return redirect($this->redirectPath())
->with('status', trans($response)); // ->with('status', trans($response));
} }
} }

View File

@ -11,7 +11,6 @@
namespace App\Http\Controllers\Bank; namespace App\Http\Controllers\Bank;
use App\Helpers\Bank\Yodlee\DTO\AccountSummary;
use App\Helpers\Bank\Yodlee\Yodlee; use App\Helpers\Bank\Yodlee\Yodlee;
use App\Http\Controllers\BaseController; use App\Http\Controllers\BaseController;
use App\Http\Requests\Yodlee\YodleeAdminRequest; use App\Http\Requests\Yodlee\YodleeAdminRequest;
@ -301,8 +300,6 @@ class YodleeController extends BaseController
$summary = $yodlee->getAccountSummary($account_number); $summary = $yodlee->getAccountSummary($account_number);
//@todo remove laravel-data
// $transformed_summary = AccountSummary::from($summary[0]);
$transformed_summary = $this->transformSummary($summary[0]); $transformed_summary = $this->transformSummary($summary[0]);
return response()->json($transformed_summary, 200); return response()->json($transformed_summary, 200);
@ -310,7 +307,7 @@ class YodleeController extends BaseController
private function transformSummary($summary): array private function transformSummary($summary): array
{ {
$dto = new \stdClass; $dto = new \stdClass();
$dto->id = $summary['id'] ?? 0; $dto->id = $summary['id'] ?? 0;
$dto->account_type = $summary['CONTAINER'] ?? ''; $dto->account_type = $summary['CONTAINER'] ?? '';

View File

@ -55,7 +55,7 @@ class BankIntegrationController extends BaseController
/** /**
* @param BankIntegrationFilters $filters * @param BankIntegrationFilters $filters
* @return Response * @return Response| \Illuminate\Http\JsonResponse
*/ */
public function index(BankIntegrationFilters $filters) public function index(BankIntegrationFilters $filters)
{ {
@ -69,7 +69,7 @@ class BankIntegrationController extends BaseController
* *
* @param ShowBankIntegrationRequest $request * @param ShowBankIntegrationRequest $request
* @param BankIntegration $bank_integration * @param BankIntegration $bank_integration
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function show(ShowBankIntegrationRequest $request, BankIntegration $bank_integration) public function show(ShowBankIntegrationRequest $request, BankIntegration $bank_integration)
@ -83,7 +83,7 @@ class BankIntegrationController extends BaseController
* *
* @param EditBankIntegrationRequest $request * @param EditBankIntegrationRequest $request
* @param BankIntegration $bank_integration * @param BankIntegration $bank_integration
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function edit(EditBankIntegrationRequest $request, BankIntegration $bank_integration) public function edit(EditBankIntegrationRequest $request, BankIntegration $bank_integration)
@ -96,7 +96,7 @@ class BankIntegrationController extends BaseController
* *
* @param UpdateBankIntegrationRequest $request * @param UpdateBankIntegrationRequest $request
* @param BankIntegration $bank_integration * @param BankIntegration $bank_integration
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function update(UpdateBankIntegrationRequest $request, BankIntegration $bank_integration) public function update(UpdateBankIntegrationRequest $request, BankIntegration $bank_integration)
@ -111,7 +111,7 @@ class BankIntegrationController extends BaseController
* Show the form for creating a new resource. * Show the form for creating a new resource.
* *
* @param CreateBankIntegrationRequest $request * @param CreateBankIntegrationRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
*/ */
@ -130,7 +130,7 @@ class BankIntegrationController extends BaseController
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param StoreBankIntegrationRequest $request * @param StoreBankIntegrationRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function store(StoreBankIntegrationRequest $request) public function store(StoreBankIntegrationRequest $request)
@ -150,7 +150,7 @@ class BankIntegrationController extends BaseController
* *
* @param DestroyBankIntegrationRequest $request * @param DestroyBankIntegrationRequest $request
* @param BankIntegration $bank_integration * @param BankIntegration $bank_integration
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* @throws \Exception * @throws \Exception
*/ */
@ -165,7 +165,7 @@ class BankIntegrationController extends BaseController
/** /**
* Perform bulk actions on the list view. * Perform bulk actions on the list view.
* *
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function bulk(BulkBankIntegrationRequest $request) public function bulk(BulkBankIntegrationRequest $request)
@ -295,7 +295,7 @@ class BankIntegrationController extends BaseController
* Return the remote list of accounts stored on the third party provider * Return the remote list of accounts stored on the third party provider
* and update our local cache. * and update our local cache.
* *
* @return Response | JsonResponse * @return Response| \Illuminate\Http\JsonResponse | JsonResponse
* *
*/ */

View File

@ -85,7 +85,7 @@ class BankTransactionRuleController extends BaseController
* ), * ),
* ) * )
* @param BankTransactionRuleFilters $filters * @param BankTransactionRuleFilters $filters
* @return Response|mixed * @return Response| \Illuminate\Http\JsonResponse|mixed
*/ */
public function index(BankTransactionRuleFilters $filters) public function index(BankTransactionRuleFilters $filters)
{ {
@ -99,7 +99,7 @@ class BankTransactionRuleController extends BaseController
* *
* @param ShowBankTransactionRuleRequest $request * @param ShowBankTransactionRuleRequest $request
* @param BankTransactionRule $bank_transaction_rule * @param BankTransactionRule $bank_transaction_rule
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Illuminate\Http\Response
* *
* *
* @OA\Get( * @OA\Get(
@ -154,7 +154,7 @@ class BankTransactionRuleController extends BaseController
* *
* @param EditBankTransactionRuleRequest $request * @param EditBankTransactionRuleRequest $request
* @param BankTransactionRule $bank_transaction_rule * @param BankTransactionRule $bank_transaction_rule
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
* *
* @OA\Get( * @OA\Get(
@ -208,7 +208,7 @@ class BankTransactionRuleController extends BaseController
* *
* @param UpdateBankTransactionRuleRequest $request * @param UpdateBankTransactionRuleRequest $request
* @param BankTransactionRule $bank_transaction_rule * @param BankTransactionRule $bank_transaction_rule
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
* *
* *
@ -269,7 +269,7 @@ class BankTransactionRuleController extends BaseController
* Show the form for creating a new resource. * Show the form for creating a new resource.
* *
* @param CreateBankTransactionRuleRequest $request * @param CreateBankTransactionRuleRequest $request
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
* *
* *
@ -317,7 +317,7 @@ class BankTransactionRuleController extends BaseController
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param StoreBankTransactionRuleRequest $request * @param StoreBankTransactionRuleRequest $request
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
* *
* *
@ -369,7 +369,7 @@ class BankTransactionRuleController extends BaseController
* *
* @param DestroyBankTransactionRuleRequest $request * @param DestroyBankTransactionRuleRequest $request
* @param BankTransactionRule $bank_transaction_rule * @param BankTransactionRule $bank_transaction_rule
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
* *
* @throws \Exception * @throws \Exception
@ -424,7 +424,7 @@ class BankTransactionRuleController extends BaseController
/** /**
* Perform bulk actions on the list view. * Perform bulk actions on the list view.
* *
* @return \Illuminate\Support\Collection * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
* *
* @OA\Post( * @OA\Post(
* path="/api/v1/bank_transation_rules/bulk", * path="/api/v1/bank_transation_rules/bulk",

View File

@ -38,7 +38,7 @@ use App\Transformers\ArraySerializer;
use App\Transformers\EntityTransformer; use App\Transformers\EntityTransformer;
use League\Fractal\Resource\Collection; use League\Fractal\Resource\Collection;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Invoiceninja\Einvoice\Decoder\Schema; use InvoiceNinja\EInvoice\Decoder\Schema;
use League\Fractal\Serializer\JsonApiSerializer; use League\Fractal\Serializer\JsonApiSerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Container\BindingResolutionException;
@ -262,7 +262,7 @@ class BaseController extends Controller
/** /**
* 404 for the client portal. * 404 for the client portal.
* @return Response 404 response * @return Response| \Illuminate\Http\JsonResponse 404 response
*/ */
public function notFoundClient() public function notFoundClient()
{ {
@ -279,7 +279,7 @@ class BaseController extends Controller
* *
* @param string|array $message The return error message * @param string|array $message The return error message
* @param int $httpErrorCode 404/401/403 etc * @param int $httpErrorCode 404/401/403 etc
* @return Response The JSON response * @return Response| \Illuminate\Http\JsonResponse The JSON response
* @throws BindingResolutionException * @throws BindingResolutionException
*/ */
protected function errorResponse($message, $httpErrorCode = 400) protected function errorResponse($message, $httpErrorCode = 400)
@ -297,7 +297,7 @@ class BaseController extends Controller
* Refresh API response with latest cahnges * Refresh API response with latest cahnges
* *
* @param Builder $query * @param Builder $query
* @return Response * @return Response| \Illuminate\Http\JsonResponse
*/ */
protected function refreshResponse($query) protected function refreshResponse($query)
{ {
@ -460,7 +460,7 @@ class BaseController extends Controller
} }
}, },
'company.tasks' => function ($query) use ($updated_at, $user) { 'company.tasks' => function ($query) use ($updated_at, $user) {
$query->where('updated_at', '>=', $updated_at)->with('project','documents'); $query->where('updated_at', '>=', $updated_at)->with('project', 'documents');
if (! $user->hasPermission('view_task')) { if (! $user->hasPermission('view_task')) {
$query->whereNested(function ($query) use ($user) { $query->whereNested(function ($query) use ($user) {
@ -798,7 +798,7 @@ class BaseController extends Controller
} }
}, },
'company.tasks' => function ($query) use ($created_at, $user) { 'company.tasks' => function ($query) use ($created_at, $user) {
$query->where('created_at', '>=', $created_at)->with('project.documents','documents'); $query->where('created_at', '>=', $created_at)->with('project.documents', 'documents');
if (! $user->hasPermission('view_task')) { if (! $user->hasPermission('view_task')) {
$query->whereNested(function ($query) use ($user) { $query->whereNested(function ($query) use ($user) {
@ -969,7 +969,7 @@ class BaseController extends Controller
* Sorts the response by keys * Sorts the response by keys
* *
* @param mixed $response * @param mixed $response
* @return Response * @return Response| \Illuminate\Http\JsonResponse
*/ */
protected function response($response) protected function response($response)
{ {
@ -995,15 +995,16 @@ class BaseController extends Controller
$response_data = Statics::company($user->getCompany()->getLocale()); $response_data = Statics::company($user->getCompany()->getLocale());
if(request()->has('einvoice')){ if(request()->has('einvoice')) {
$ro = new Schema();
$response_data['einvoice_schema'] = $ro('FACT1');
if(class_exists(Schema::class)){
$ro = new Schema();
$response_data['einvoice_schema'] = $ro('Peppol');
}
} }
$response['static'] = $response_data; $response['static'] = $response_data;
} }
} }
@ -1020,7 +1021,7 @@ class BaseController extends Controller
* Item Response * Item Response
* *
* @param mixed $item * @param mixed $item
* @return Response * @return Response| \Illuminate\Http\JsonResponse
*/ */
protected function itemResponse($item) protected function itemResponse($item)
{ {
@ -1034,7 +1035,7 @@ class BaseController extends Controller
$resource = new Item($item, $transformer, $this->entity_type); $resource = new Item($item, $transformer, $this->entity_type);
/** @var \App\Models\User $user */ /** @var ?\App\Models\User $user */
$user = auth()->user(); $user = auth()->user();
if ($user && request()->include_static) { if ($user && request()->include_static) {

View File

@ -19,7 +19,6 @@ use Illuminate\Http\Request;
*/ */
class BrevoController extends BaseController class BrevoController extends BaseController
{ {
private $invitation;
public function __construct() public function __construct()
{ {

View File

@ -89,7 +89,7 @@ class ClientController extends BaseController
/** /**
* *
* @param ClientFilters $filters * @param ClientFilters $filters
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function index(ClientFilters $filters) public function index(ClientFilters $filters)
@ -106,7 +106,7 @@ class ClientController extends BaseController
* *
* @param ShowClientRequest $request * @param ShowClientRequest $request
* @param Client $client * @param Client $client
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function show(ShowClientRequest $request, Client $client) public function show(ShowClientRequest $request, Client $client)
@ -119,7 +119,7 @@ class ClientController extends BaseController
* *
* @param EditClientRequest $request * @param EditClientRequest $request
* @param Client $client * @param Client $client
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function edit(EditClientRequest $request, Client $client) public function edit(EditClientRequest $request, Client $client)
@ -132,7 +132,7 @@ class ClientController extends BaseController
* *
* @param UpdateClientRequest $request * @param UpdateClientRequest $request
* @param Client $client * @param Client $client
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function update(UpdateClientRequest $request, Client $client) public function update(UpdateClientRequest $request, Client $client)
@ -141,7 +141,7 @@ class ClientController extends BaseController
return $request->disallowUpdate(); return $request->disallowUpdate();
} }
/** @var \App\Models\User $user */ /** @var ?\App\Models\User $user */
$user = auth()->user(); $user = auth()->user();
$client = $this->client_repo->save($request->all(), $client); $client = $this->client_repo->save($request->all(), $client);
@ -157,7 +157,7 @@ class ClientController extends BaseController
* Show the form for creating a new resource. * Show the form for creating a new resource.
* *
* @param CreateClientRequest $request * @param CreateClientRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function create(CreateClientRequest $request) public function create(CreateClientRequest $request)
@ -174,7 +174,7 @@ class ClientController extends BaseController
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param StoreClientRequest $request * @param StoreClientRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function store(StoreClientRequest $request) public function store(StoreClientRequest $request)
@ -203,7 +203,7 @@ class ClientController extends BaseController
* *
* @param DestroyClientRequest $request * @param DestroyClientRequest $request
* @param Client $client * @param Client $client
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* @throws \Exception * @throws \Exception
*/ */
@ -217,7 +217,7 @@ class ClientController extends BaseController
/** /**
* Perform bulk actions on the list view. * Perform bulk actions on the list view.
* *
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function bulk(BulkClientRequest $request) public function bulk(BulkClientRequest $request)
@ -250,22 +250,22 @@ class ClientController extends BaseController
return response()->json(['message' => $hash_or_response], 200); return response()->json(['message' => $hash_or_response], 200);
} }
if($action == 'assign_group' && $user->can('edit', $clients->first())){ if($action == 'assign_group' && $user->can('edit', $clients->first())) {
$this->client_repo->assignGroup($clients, $request->group_settings_id); $this->client_repo->assignGroup($clients, $request->group_settings_id);
return $this->listResponse(Client::query()->withTrashed()->company()->whereIn('id', $request->ids)); return $this->listResponse(Client::query()->withTrashed()->company()->whereIn('id', $request->ids));
} }
if($action == 'bulk_update' && $user->can('edit', $clients->first())){ if($action == 'bulk_update' && $user->can('edit', $clients->first())) {
$clients = Client::withTrashed() $clients = Client::withTrashed()
->company() ->company()
->whereIn('id', $request->ids); ->whereIn('id', $request->ids);
$this->client_repo->bulkUpdate($clients, $request->column, $request->new_value); $this->client_repo->bulkUpdate($clients, $request->column, $request->new_value);
return $this->listResponse(Client::query()->withTrashed()->company()->whereIn('id', $request->ids)); return $this->listResponse(Client::query()->withTrashed()->company()->whereIn('id', $request->ids));
} }
@ -284,7 +284,7 @@ class ClientController extends BaseController
* *
* @param UploadClientRequest $request * @param UploadClientRequest $request
* @param Client $client * @param Client $client
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
*/ */
public function upload(UploadClientRequest $request, Client $client) public function upload(UploadClientRequest $request, Client $client)
@ -305,7 +305,7 @@ class ClientController extends BaseController
* *
* @param PurgeClientRequest $request * @param PurgeClientRequest $request
* @param Client $client * @param Client $client
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
*/ */
public function purge(PurgeClientRequest $request, Client $client) public function purge(PurgeClientRequest $request, Client $client)
@ -333,7 +333,7 @@ class ClientController extends BaseController
* @param PurgeClientRequest $request * @param PurgeClientRequest $request
* @param Client $client * @param Client $client
* @param string $mergeable_client * @param string $mergeable_client
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
* *
*/ */
@ -351,9 +351,10 @@ class ClientController extends BaseController
return response()->json(['message' => "Client not found"], 400); return response()->json(['message' => "Client not found"], 400);
} }
if($m_client->id == $client->id) if($m_client->id == $client->id) {
return response()->json(['message' => "Attempting to merge the same client is not possible."], 400); return response()->json(['message' => "Attempting to merge the same client is not possible."], 400);
}
$merged_client = $client->service()->merge($m_client)->save(); $merged_client = $client->service()->merge($m_client)->save();
return $this->itemResponse($merged_client); return $this->itemResponse($merged_client);
@ -364,7 +365,7 @@ class ClientController extends BaseController
* *
* @param PurgeClientRequest $request * @param PurgeClientRequest $request
* @param Client $client * @param Client $client
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
*/ */
public function updateTaxData(PurgeClientRequest $request, Client $client) public function updateTaxData(PurgeClientRequest $request, Client $client)
{ {
@ -380,7 +381,7 @@ class ClientController extends BaseController
* *
* @param ReactivateClientEmailRequest $request * @param ReactivateClientEmailRequest $request
* @param string $bounce_id //could also be the invitationId * @param string $bounce_id //could also be the invitationId
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
*/ */
public function reactivateEmail(ReactivateClientEmailRequest $request, string $bounce_id) public function reactivateEmail(ReactivateClientEmailRequest $request, string $bounce_id)
{ {
@ -425,7 +426,7 @@ class ClientController extends BaseController
try { try {
/** @var \Postmark\Models\DynamicResponseModel $response */ /** @var ?\Postmark\Models\DynamicResponseModel $response */
$response = $postmark->activateBounce((int)$bounce_id); $response = $postmark->activateBounce((int)$bounce_id);
if($response && $response?->Message == 'OK' && !$response->Bounce->Inactive && $response->Bounce->Email) { if($response && $response?->Message == 'OK' && !$response->Bounce->Inactive && $response->Bounce->Email) {

View File

@ -89,7 +89,7 @@ class ClientGatewayTokenController extends BaseController
* ), * ),
* ) * )
* @param ListClientGatewayTokenRequest $request * @param ListClientGatewayTokenRequest $request
* @return Response|mixed * @return Response| \Illuminate\Http\JsonResponse|mixed
*/ */
public function index(ListClientGatewayTokenRequest $request) public function index(ListClientGatewayTokenRequest $request)
{ {
@ -103,7 +103,7 @@ class ClientGatewayTokenController extends BaseController
* *
* @param ShowClientGatewayTokenRequest $request * @param ShowClientGatewayTokenRequest $request
* @param ClientGatewayToken $client_gateway_token * @param ClientGatewayToken $client_gateway_token
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Get( * @OA\Get(
@ -157,7 +157,7 @@ class ClientGatewayTokenController extends BaseController
* *
* @param EditClientGatewayTokenRequest $request * @param EditClientGatewayTokenRequest $request
* @param ClientGatewayToken $client_gateway_token * @param ClientGatewayToken $client_gateway_token
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Get( * @OA\Get(
@ -211,7 +211,7 @@ class ClientGatewayTokenController extends BaseController
* *
* @param UpdateClientGatewayTokenRequest $request * @param UpdateClientGatewayTokenRequest $request
* @param ClientGatewayToken $client_gateway_token * @param ClientGatewayToken $client_gateway_token
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -267,7 +267,7 @@ class ClientGatewayTokenController extends BaseController
* Show the form for creating a new resource. * Show the form for creating a new resource.
* *
* @param CreateClientGatewayTokenRequest $request * @param CreateClientGatewayTokenRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -317,7 +317,7 @@ class ClientGatewayTokenController extends BaseController
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param StoreClientGatewayTokenRequest $request * @param StoreClientGatewayTokenRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -369,7 +369,7 @@ class ClientGatewayTokenController extends BaseController
* *
* @param DestroyClientGatewayTokenRequest $request * @param DestroyClientGatewayTokenRequest $request
* @param ClientGatewayToken $client_gateway_token * @param ClientGatewayToken $client_gateway_token
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @throws \Exception * @throws \Exception

View File

@ -21,7 +21,7 @@ class ContactHashLoginController extends Controller
/** /**
* Logs a user into the client portal using their contact_key * Logs a user into the client portal using their contact_key
* @param string $contact_key The contact key * @param string $contact_key The contact key
* @return Redirect * @return \Illuminate\Http\RedirectResponse
*/ */
public function login(string $contact_key) public function login(string $contact_key)
{ {
@ -50,7 +50,7 @@ class ContactHashLoginController extends Controller
/** /**
* Generic error page for client portal. * Generic error page for client portal.
* *
* @return void * @return \Illuminate\View\View
*/ */
public function errorPage() public function errorPage()
{ {
@ -66,15 +66,15 @@ class ContactHashLoginController extends Controller
{ {
if (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES) { if (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES) {
return '/client/invoices'; return '/client/invoices';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES)) {
return '/client/recurring_invoices'; return '/client/recurring_invoices';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES)) {
return '/client/quotes'; return '/client/quotes';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS)) {
return '/client/credits'; return '/client/credits';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_TASKS) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_TASKS)) {
return '/client/tasks'; return '/client/tasks';
} elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_EXPENSES) { } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_EXPENSES)) {
return '/client/expenses'; return '/client/expenses';
} }
} }

View File

@ -21,7 +21,7 @@ class DashboardController extends Controller
{ {
if (auth()->guard('contact')->user()->client->getSetting('enable_client_portal_dashboard') === false) { if (auth()->guard('contact')->user()->client->getSetting('enable_client_portal_dashboard') === false) {
return redirect()->route('client.invoices.index'); return redirect()->route('client.invoices.index');
} }
$total_invoices = Invoice::withTrashed() $total_invoices = Invoice::withTrashed()
->where('client_id', auth()->guard('contact')->user()->client_id) ->where('client_id', auth()->guard('contact')->user()->client_id)

View File

@ -114,15 +114,17 @@ class InvitationController extends Controller
'invitation_key' => $invitation_key 'invitation_key' => $invitation_key
]); ]);
} }
if(!auth()->guard('contact')->check()){
$this->middleware('auth:contact');
return redirect()->route('client.login', ['intended' => route('client.'.$entity.'.show', [$entity => $this->encodePrimaryKey($invitation->{$key}), 'silent' => $is_silent])]);
}
$this->middleware('auth:contact');
return redirect()->route('client.login');
} else { } else {
request()->session()->invalidate(); request()->session()->invalidate();
auth()->guard('contact')->loginUsingId($client_contact->id, true); auth()->guard('contact')->loginUsingId($client_contact->id, true);
} }
if (auth()->guard('contact')->user() && ! request()->has('silent') && ! $invitation->viewed_date) { if (auth()->guard('contact')->user() && ! request()->has('silent') && ! $invitation->viewed_date) {
$invitation->markViewed(); $invitation->markViewed();
@ -144,6 +146,7 @@ class InvitationController extends Controller
} }
private function fireEntityViewedEvent($invitation, $entity_string) private function fireEntityViewedEvent($invitation, $entity_string)
{ {
switch ($entity_string) { switch ($entity_string) {

View File

@ -97,12 +97,12 @@ class InvoiceController extends Controller
$invitation = false; $invitation = false;
match($data['entity_type'] ?? false) { match($data['entity_type'] ?? 'invoice') {
'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']), 'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']),
'quote' => $invitation = QuoteInvitation::withTrashed()->find($data['invitation_id']), 'quote' => $invitation = QuoteInvitation::withTrashed()->find($data['invitation_id']),
'credit' => $invitation = CreditInvitation::withTrashed()->find($data['invitation_id']), 'credit' => $invitation = CreditInvitation::withTrashed()->find($data['invitation_id']),
'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->find($data['invitation_id']), 'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->find($data['invitation_id']),
false => $invitation = false, default => $invitation = false,
}; };
if (! $invitation) { if (! $invitation) {

View File

@ -77,6 +77,7 @@ class PaymentController extends Controller
'EUR' => $data = $bt->formatDataforEur($payment_intent), 'EUR' => $data = $bt->formatDataforEur($payment_intent),
'JPY' => $data = $bt->formatDataforJp($payment_intent), 'JPY' => $data = $bt->formatDataforJp($payment_intent),
'GBP' => $data = $bt->formatDataforUk($payment_intent), 'GBP' => $data = $bt->formatDataforUk($payment_intent),
default => $data = $bt->formatDataforUk($payment_intent),
}; };
$gateway = $stripe; $gateway = $stripe;
@ -103,7 +104,7 @@ class PaymentController extends Controller
* and invoice ids for reference. * and invoice ids for reference.
* *
* @param Request $request * @param Request $request
* @return RedirectResponse|mixed * @return \Illuminate\Http\RedirectResponse|mixed
*/ */
public function process(Request $request) public function process(Request $request)
{ {
@ -157,7 +158,7 @@ class PaymentController extends Controller
* Pay for invoice/s using credits only. * Pay for invoice/s using credits only.
* *
* @param Request $request The request object * @param Request $request The request object
* @return \Response The response view * @return \Illuminate\Http\RedirectResponse The response view
*/ */
public function credit_response(Request $request) public function credit_response(Request $request)
{ {

View File

@ -127,7 +127,7 @@ class PaymentMethodController extends Controller
* Remove the specified resource from storage. * Remove the specified resource from storage.
* *
* @param ClientGatewayToken $payment_method * @param ClientGatewayToken $payment_method
* @return RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(ClientGatewayToken $payment_method) public function destroy(ClientGatewayToken $payment_method)
{ {

View File

@ -48,6 +48,9 @@ class PrePaymentController extends Controller
'allows_recurring' => true, 'allows_recurring' => true,
'minimum' => $minimum, 'minimum' => $minimum,
'minimum_amount' => $minimum_amount, 'minimum_amount' => $minimum_amount,
'notes' => request()->has('notes') ? request()->input('notes') : "",
'amount' => request()->has('amount') ? request()->input('amount') : "",
'show' => request()->has('is_recurring') ? "true" : "false",
]; ];
return $this->render('pre_payments.index', $data); return $this->render('pre_payments.index', $data);
@ -105,7 +108,7 @@ class PrePaymentController extends Controller
return $invoice; return $invoice;
}); });
$variables = false; $variables = false;
if(($invitation = $invoices->first()->invitations()->first() ?? false) && $invoice->client->getSetting('show_accept_invoice_terms')) { if(($invitation = $invoices->first()->invitations()->first() ?? false) && $invoice->client->getSetting('show_accept_invoice_terms')) {

View File

@ -38,7 +38,7 @@ class ProfileController extends Controller
* *
* @param UpdateContactRequest $request * @param UpdateContactRequest $request
* @param ClientContact $client_contact * @param ClientContact $client_contact
* @return RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function update(UpdateContactRequest $request, ClientContact $client_contact) public function update(UpdateContactRequest $request, ClientContact $client_contact)
{ {

View File

@ -178,7 +178,7 @@ class QuoteController extends Controller
->where('client_id', auth()->guard('contact')->user()->client->id) ->where('client_id', auth()->guard('contact')->user()->client->id)
->where('company_id', auth()->guard('contact')->user()->client->company_id) ->where('company_id', auth()->guard('contact')->user()->client->company_id)
->whereIn('status_id', [Quote::STATUS_DRAFT, Quote::STATUS_SENT]) ->whereIn('status_id', [Quote::STATUS_DRAFT, Quote::STATUS_SENT])
->where(function ($q){ ->where(function ($q) {
$q->whereNull('due_date')->orWhere('due_date', '>=', now()); $q->whereNull('due_date')->orWhere('due_date', '>=', now());
}) })
->withTrashed() ->withTrashed()

View File

@ -66,7 +66,7 @@ class RecurringInvoiceController extends Controller
* @param RequestCancellationRequest $request [description] * @param RequestCancellationRequest $request [description]
* @param RecurringInvoice $recurring_invoice [description] * @param RecurringInvoice $recurring_invoice [description]
* *
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/ */
public function requestCancellation(RequestCancellationRequest $request, RecurringInvoice $recurring_invoice) public function requestCancellation(RequestCancellationRequest $request, RecurringInvoice $recurring_invoice)
{ {

View File

@ -90,15 +90,20 @@ class SubscriptionPurchaseController extends Controller
* Set locale for incoming request. * Set locale for incoming request.
* *
* @param string $locale * @param string $locale
* @return string
*/ */
private function setLocale(string $locale): void private function setLocale(string $locale): string
{ {
$record = Cache::get('languages')->filter(function ($item) use ($locale) {
return $item->locale == $locale; /** @var \Illuminate\Support\Collection<\App\Models\Language> */
})->first(); $languages = app('languages');
if ($record) { $record = $languages->first(function ($item) use ($locale) {
App::setLocale($record->locale); /** @var \App\Models\Language $item */
} return $item->locale == $locale;
});
return $record ? $record->locale : 'en';
} }
} }

View File

@ -13,14 +13,13 @@ namespace App\Http\Controllers\ClientPortal;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redirect;
class TempRouteController extends Controller class TempRouteController extends Controller
{ {
/** /**
* Logs a user into the client portal using their contact_key * Logs a user into the client portal using their contact_key
* @param string $hash The hash * @param string $hash The hash
* @return Redirect * @return \Illuminate\View\View
*/ */
public function index(string $hash) public function index(string $hash)
{ {

View File

@ -26,7 +26,7 @@ class UploadController extends Controller
* Main logic behind uploading the files. * Main logic behind uploading the files.
* *
* @param StoreUploadRequest $request * @param StoreUploadRequest $request
* @return Response|ResponseFactory * @return Response| \Illuminate\Http\JsonResponse|ResponseFactory
*/ */
public function __invoke(StoreUploadRequest $request) public function __invoke(StoreUploadRequest $request)
{ {

View File

@ -33,7 +33,7 @@ class ClientStatementController extends BaseController
* Update the specified resource in storage. * Update the specified resource in storage.
* *
* @param CreateStatementRequest $request * @param CreateStatementRequest $request
* @return Response * @return \Symfony\Component\HttpFoundation\StreamedResponse | \Illuminate\Http\JsonResponse
*/ */
public function statement(CreateStatementRequest $request) public function statement(CreateStatementRequest $request)
{ {

View File

@ -78,7 +78,7 @@ class CompanyController extends BaseController
/** /**
* Display a listing of the resource. * Display a listing of the resource.
* *
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* @OA\Get( * @OA\Get(
* path="/api/v1/companies", * path="/api/v1/companies",
@ -117,16 +117,26 @@ class CompanyController extends BaseController
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = auth()->user(); $user = auth()->user();
$companies = Company::whereAccountId($user->company()->account->id); $companies = Company::where('account_id', $user->company()->account->id);
return $this->listResponse($companies); return $this->listResponse($companies);
} }
public function current()
{
/** @var \App\Models\User $user */
$user = auth()->user();
$company = Company::find($user->company()->id);
return $this->itemResponse($company);
}
/** /**
* Show the form for creating a new resource. * Show the form for creating a new resource.
* *
* @param CreateCompanyRequest $request * @param CreateCompanyRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -176,7 +186,7 @@ class CompanyController extends BaseController
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param StoreCompanyRequest $request * @param StoreCompanyRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Post( * @OA\Post(
@ -262,7 +272,7 @@ class CompanyController extends BaseController
* *
* @param ShowCompanyRequest $request * @param ShowCompanyRequest $request
* @param Company $company * @param Company $company
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Get( * @OA\Get(
@ -316,7 +326,7 @@ class CompanyController extends BaseController
* *
* @param EditCompanyRequest $request * @param EditCompanyRequest $request
* @param Company $company * @param Company $company
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Get( * @OA\Get(
@ -370,7 +380,7 @@ class CompanyController extends BaseController
* *
* @param UpdateCompanyRequest $request * @param UpdateCompanyRequest $request
* @param Company $company * @param Company $company
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Put( * @OA\Put(
@ -447,7 +457,7 @@ class CompanyController extends BaseController
* *
* @param DestroyCompanyRequest $request * @param DestroyCompanyRequest $request
* @param Company $company * @param Company $company
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @throws \Exception * @throws \Exception
@ -563,7 +573,7 @@ class CompanyController extends BaseController
* *
* @param UploadCompanyRequest $request * @param UploadCompanyRequest $request
* @param Company $company * @param Company $company
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -626,7 +636,7 @@ class CompanyController extends BaseController
* *
* @param DefaultCompanyRequest $request * @param DefaultCompanyRequest $request
* @param Company $company * @param Company $company
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -683,7 +693,7 @@ class CompanyController extends BaseController
public function updateOriginTaxData(DefaultCompanyRequest $request, Company $company) public function updateOriginTaxData(DefaultCompanyRequest $request, Company $company)
{ {
if($company->settings->country_id == "840" && !$company?->account->isFreeHostedClient()) { if($company->settings->country_id == "840" && !$company->account->isFreeHostedClient()) {
try { try {
(new CompanyTaxRate($company))->handle(); (new CompanyTaxRate($company))->handle();
} catch(\Exception $e) { } catch(\Exception $e) {
@ -696,6 +706,11 @@ class CompanyController extends BaseController
return $this->itemResponse($company->fresh()); return $this->itemResponse($company->fresh());
} }
/**
*
*
* @return \Symfony\Component\HttpFoundation\StreamedResponse | \Illuminate\Http\JsonResponse
*/
public function logo() public function logo()
{ {
@ -705,18 +720,16 @@ class CompanyController extends BaseController
$logo = strlen($company->settings->company_logo) > 5 ? $company->settings->company_logo : 'https://pdf.invoicing.co/favicon-v2.png'; $logo = strlen($company->settings->company_logo) > 5 ? $company->settings->company_logo : 'https://pdf.invoicing.co/favicon-v2.png';
$headers = ['Content-Disposition' => 'inline']; $headers = ['Content-Disposition' => 'inline'];
try{ try {
$response = \Illuminate\Support\Facades\Http::get($logo); $response = \Illuminate\Support\Facades\Http::get($logo);
if ($response->successful()) { if ($response->successful()) {
$logo = $response->body(); $logo = $response->body();
} } else {
else {
$logo = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='); $logo = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=');
} }
} } catch(\Exception $e) {
catch(\Exception $e){
$logo = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='); $logo = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=');

View File

@ -72,7 +72,7 @@ class CompanyGatewayController extends BaseController
/** /**
* Display a listing of the resource. * Display a listing of the resource.
* *
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -119,7 +119,7 @@ class CompanyGatewayController extends BaseController
* Show the form for creating a new resource. * Show the form for creating a new resource.
* *
* @param CreateCompanyGatewayRequest $request * @param CreateCompanyGatewayRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -168,7 +168,7 @@ class CompanyGatewayController extends BaseController
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param StoreCompanyGatewayRequest $request * @param StoreCompanyGatewayRequest $request
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* *
@ -232,7 +232,7 @@ class CompanyGatewayController extends BaseController
} elseif($company_gateway->gateway_key == $this->checkout_key) { } elseif($company_gateway->gateway_key == $this->checkout_key) {
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id); CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
} elseif($company_gateway->gateway_key == $this->forte_key) { } elseif($company_gateway->gateway_key == $this->forte_key) {
dispatch(function () use ($company_gateway) { dispatch(function () use ($company_gateway) {
MultiDB::setDb($company_gateway->company->db); MultiDB::setDb($company_gateway->company->db);
$company_gateway->driver()->updateFees(); $company_gateway->driver()->updateFees();
@ -248,7 +248,7 @@ class CompanyGatewayController extends BaseController
* *
* @param ShowCompanyGatewayRequest $request * @param ShowCompanyGatewayRequest $request
* @param CompanyGateway $company_gateway * @param CompanyGateway $company_gateway
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Get( * @OA\Get(
@ -302,7 +302,7 @@ class CompanyGatewayController extends BaseController
* *
* @param EditCompanyGatewayRequest $request * @param EditCompanyGatewayRequest $request
* @param CompanyGateway $company_gateway * @param CompanyGateway $company_gateway
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Get( * @OA\Get(
@ -356,7 +356,7 @@ class CompanyGatewayController extends BaseController
* *
* @param UpdateCompanyGatewayRequest $request * @param UpdateCompanyGatewayRequest $request
* @param CompanyGateway $company_gateway * @param CompanyGateway $company_gateway
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Put( * @OA\Put(
@ -420,8 +420,8 @@ class CompanyGatewayController extends BaseController
if($company_gateway->gateway_key == $this->checkout_key) { if($company_gateway->gateway_key == $this->checkout_key) {
CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->fresh()->id); CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->fresh()->id);
}elseif($company_gateway->gateway_key == $this->forte_key){ } elseif($company_gateway->gateway_key == $this->forte_key) {
dispatch(function () use ($company_gateway) { dispatch(function () use ($company_gateway) {
MultiDB::setDb($company_gateway->company->db); MultiDB::setDb($company_gateway->company->db);
$company_gateway->driver()->updateFees(); $company_gateway->driver()->updateFees();
@ -437,7 +437,7 @@ class CompanyGatewayController extends BaseController
* *
* @param DestroyCompanyGatewayRequest $request * @param DestroyCompanyGatewayRequest $request
* @param CompanyGateway $company_gateway * @param CompanyGateway $company_gateway
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @throws \Exception * @throws \Exception
@ -494,7 +494,7 @@ class CompanyGatewayController extends BaseController
/** /**
* Perform bulk actions on the list view. * Perform bulk actions on the list view.
* *
* @return Response * @return Response| \Illuminate\Http\JsonResponse
* *
* *
* @OA\Post( * @OA\Post(
@ -565,12 +565,13 @@ class CompanyGatewayController extends BaseController
public function importCustomers(TestCompanyGatewayRequest $request, CompanyGateway $company_gateway) public function importCustomers(TestCompanyGatewayRequest $request, CompanyGateway $company_gateway)
{ {
//Throttle here
if (Cache::has("throttle_polling:import_customers:{$company_gateway->company->company_key}:{$company_gateway->hashed_id}"))
return response()->json(['message' => 'Please wait whilst your previous attempts complete.'], 200);
dispatch(function () use($company_gateway) { //Throttle here
if (Cache::has("throttle_polling:import_customers:{$company_gateway->company->company_key}:{$company_gateway->hashed_id}")) {
return response()->json(['message' => 'Please wait whilst your previous attempts complete.'], 200);
}
dispatch(function () use ($company_gateway) {
MultiDB::setDb($company_gateway->company->db); MultiDB::setDb($company_gateway->company->db);
$company_gateway->driver()->importCustomers(); $company_gateway->driver()->importCustomers();
})->afterResponse(); })->afterResponse();

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