diff --git a/VERSION.txt b/VERSION.txt index 71c2c6e276..57ebcacf2c 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.33 \ No newline at end of file +5.7.34 \ No newline at end of file diff --git a/app/Casts/EncryptedCast.php b/app/Casts/EncryptedCast.php index 7be926072c..a8c11f3ad3 100644 --- a/app/Casts/EncryptedCast.php +++ b/app/Casts/EncryptedCast.php @@ -16,12 +16,12 @@ use Illuminate\Contracts\Database\Eloquent\CastsAttributes; class EncryptedCast implements CastsAttributes { public function get($model, string $key, $value, array $attributes) - { + { return is_string($value) && strlen($value) > 1 ? decrypt($value) : null; } public function set($model, string $key, $value, array $attributes) - { + { return [$key => ! is_null($value) ? encrypt($value) : null]; } } diff --git a/app/Console/Commands/BackupUpdate.php b/app/Console/Commands/BackupUpdate.php index 9a827b68d1..b6f1cb4f5b 100644 --- a/app/Console/Commands/BackupUpdate.php +++ b/app/Console/Commands/BackupUpdate.php @@ -11,13 +11,13 @@ namespace App\Console\Commands; -use App\Utils\Ninja; +use App\Libraries\MultiDB; use App\Models\Backup; use App\Models\Client; use App\Models\Company; use App\Models\Document; -use App\Libraries\MultiDB; use App\Models\GroupSetting; +use App\Utils\Ninja; use Illuminate\Console\Command; use Illuminate\Support\Facades\Storage; @@ -56,8 +56,9 @@ class BackupUpdate extends Command { //always return state to first DB - if(Ninja::isSelfHost()) + if(Ninja::isSelfHost()) { return; + } $current_db = config('database.default'); diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index 7c5a3f21bb..89492f8fe2 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -12,38 +12,37 @@ namespace App\Console\Commands; use App; -use Exception; -use App\Models\User; -use App\Utils\Ninja; -use App\Models\Quote; -use App\Models\Client; -use App\Models\Credit; -use App\Models\Vendor; -use App\Models\Account; -use App\Models\Company; -use App\Models\Contact; -use App\Models\Invoice; -use App\Models\Payment; -use App\Models\CompanyUser; -use Illuminate\Support\Str; -use App\Models\CompanyToken; -use App\Models\ClientContact; -use App\Models\CompanyLedger; -use App\Models\PurchaseOrder; -use App\Models\VendorContact; -use App\Models\BankTransaction; -use App\Models\QuoteInvitation; -use Illuminate\Console\Command; -use App\Models\CreditInvitation; -use App\Models\RecurringInvoice; -use App\Models\InvoiceInvitation; use App\DataMapper\ClientSettings; -use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Mail; use App\Factory\ClientContactFactory; use App\Factory\VendorContactFactory; use App\Jobs\Company\CreateCompanyToken; +use App\Models\Account; +use App\Models\BankTransaction; +use App\Models\Client; +use App\Models\ClientContact; +use App\Models\Company; +use App\Models\CompanyLedger; +use App\Models\CompanyToken; +use App\Models\CompanyUser; +use App\Models\Contact; +use App\Models\Credit; +use App\Models\CreditInvitation; +use App\Models\Invoice; +use App\Models\InvoiceInvitation; +use App\Models\Payment; +use App\Models\PurchaseOrder; +use App\Models\Quote; +use App\Models\QuoteInvitation; +use App\Models\RecurringInvoice; use App\Models\RecurringInvoiceInvitation; +use App\Models\User; +use App\Models\Vendor; +use App\Models\VendorContact; +use App\Utils\Ninja; +use Illuminate\Console\Command; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Str; use Symfony\Component\Console\Input\InputOption; /* @@ -185,8 +184,7 @@ class CheckData extends Command if ($cu->company && $cu->user) { (new CreateCompanyToken($cu->company, $cu->user, 'System'))->handle(); - } - else { + } else { // $cu->forceDelete(); } } @@ -445,7 +443,7 @@ class CheckData extends Command QuoteInvitation::where('deleted_at', "0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]); CreditInvitation::where('deleted_at', "0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]); - InvoiceInvitation::where('sent_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii){ + InvoiceInvitation::where('sent_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii) { $ii->sent_date = null; $ii->saveQuietly(); }); @@ -619,7 +617,7 @@ class CheckData extends Command } $this->logMessage("{$this->wrong_paid_to_dates} clients with incorrect paid to dates"); - } + } private function clientBalanceQuery() { @@ -1028,7 +1026,7 @@ class CheckData extends Command { $this->logMessage("checking bank transactions"); - BankTransaction::with('payment')->withTrashed()->where('invoice_ids', ',,,,,,,,')->cursor()->each(function ($bt){ + BankTransaction::with('payment')->withTrashed()->where('invoice_ids', ',,,,,,,,')->cursor()->each(function ($bt) { if($bt->payment->exists()) { @@ -1052,7 +1050,7 @@ class CheckData extends Command if ($this->option('fix') == 'true') { - $q->cursor()->each(function ($c){ + $q->cursor()->each(function ($c) { $c->send_email = false; $c->saveQuietly(); diff --git a/app/Console/Commands/CreateAccount.php b/app/Console/Commands/CreateAccount.php index d2ff960b20..d56433d42b 100644 --- a/app/Console/Commands/CreateAccount.php +++ b/app/Console/Commands/CreateAccount.php @@ -20,7 +20,6 @@ use App\Models\Account; use App\Models\Company; use App\Models\CompanyToken; use App\Models\User; -use App\Repositories\InvoiceRepository; use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; use Illuminate\Console\Command; diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index a28eb64e23..33196439f7 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -36,6 +36,7 @@ use App\Models\CompanyToken; use App\Models\Country; use App\Models\Credit; use App\Models\Expense; +use App\Models\Invoice; use App\Models\Product; use App\Models\Project; use App\Models\Quote; @@ -303,6 +304,62 @@ class CreateSingleAccount extends Command $this->createGateways($company, $user); $this->createSubsData($company, $user); + + + $repo = new \App\Repositories\TaskRepository(); + + Task::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + $repo = new \App\Repositories\ExpenseRepository(); + + Expense::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + $repo = new \App\Repositories\VendorRepository(new \App\Repositories\VendorContactRepository()); + Vendor::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + $repo = new \App\Repositories\ClientRepository(new \App\Repositories\ClientContactRepository()); + Client::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + $repo = new \App\Repositories\RecurringInvoiceRepository(); + RecurringInvoice::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + $repo = new \App\Repositories\InvoiceRepository(); + Invoice::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + $repo = new \App\Repositories\QuoteRepository(); + Quote::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + $repo = new \App\Repositories\CreditRepository(); + Credit::query()->cursor()->each(function ($t) use ($repo) { + $repo->save([], $t); + }); + + + Project::query()->with('client')->whereNotNull('client_id')->cursor()->each(function ($p) { + + if($p && $p->client && !isset($p->number)) { + $p->number = $this->getNextProjectNumber($p); + $p->save(); + } + + }); + + $this->info("finished"); + } private function createSubsData($company, $user) @@ -403,7 +460,7 @@ class CreateSingleAccount extends Command $settings = $client->settings; $settings->currency_id = "1"; -// $settings->use_credits_payment = "always"; + // $settings->use_credits_payment = "always"; $client->settings = $settings; @@ -885,11 +942,11 @@ class CreateSingleAccount extends Command } } - private function createRecurringInvoice($client) + private function createRecurringInvoice(Client $client) { $faker = Factory::create(); - $invoice = RecurringInvoiceFactory::create($client->company->id, $client->user->id); //stub the company and user_id + $invoice = RecurringInvoiceFactory::create($client->company_id, $client->user_id); //stub the company and user_id $invoice->client_id = $client->id; $dateable = Carbon::now()->subDays(rand(0, 90)); $invoice->date = $dateable; diff --git a/app/Console/Commands/CreateTestData.php b/app/Console/Commands/CreateTestData.php index ca8417573c..b882c9af6d 100644 --- a/app/Console/Commands/CreateTestData.php +++ b/app/Console/Commands/CreateTestData.php @@ -496,7 +496,7 @@ class CreateTestData extends Command $invoice = InvoiceFactory::create($client->company->id, $client->user->id); //stub the company and user_id $invoice->client_id = $client->id; -// $invoice->date = $faker->date(); + // $invoice->date = $faker->date(); $dateable = Carbon::now()->subDays(rand(0, 90)); $invoice->date = $dateable; diff --git a/app/Console/Commands/ImportMigrations.php b/app/Console/Commands/ImportMigrations.php index 9e227c72bd..57d25844cb 100644 --- a/app/Console/Commands/ImportMigrations.php +++ b/app/Console/Commands/ImportMigrations.php @@ -18,7 +18,6 @@ use App\Exceptions\ProcessingMigrationArchiveFailed; use App\Exceptions\ResourceDependencyMissing; use App\Exceptions\ResourceNotAvailableForMigration; use App\Jobs\Util\Import; -use App\Jobs\Util\StartMigration; use App\Mail\MigrationFailed; use App\Models\Account; use App\Models\Company; diff --git a/app/Console/Commands/ReactBuilder.php b/app/Console/Commands/ReactBuilder.php index 6e8b3e10be..d40a250323 100644 --- a/app/Console/Commands/ReactBuilder.php +++ b/app/Console/Commands/ReactBuilder.php @@ -52,8 +52,7 @@ class ReactBuilder extends Command try { $directoryIterator = new \RecursiveDirectoryIterator(public_path('react/v'.config('ninja.app_version').'/'), \RecursiveDirectoryIterator::SKIP_DOTS); - } - catch (\Exception $e) { + } catch (\Exception $e) { $this->error('React files not found'); return; } @@ -61,14 +60,14 @@ class ReactBuilder extends Command foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) { if ($file->getExtension() == 'js') { if (str_contains($file->getFileName(), 'index-')) { - $includes .= ''."\n"; + $includes .= ''."\n"; } else { - $includes .= ''."\n"; + $includes .= ''."\n"; } } if (str_contains($file->getFileName(), '.css')) { - $includes .= ''."\n"; + $includes .= ''."\n"; } } diff --git a/app/Console/Commands/SendRemindersCron.php b/app/Console/Commands/SendRemindersCron.php index 8328611b83..ab55404fec 100644 --- a/app/Console/Commands/SendRemindersCron.php +++ b/app/Console/Commands/SendRemindersCron.php @@ -174,7 +174,7 @@ class SendRemindersCron extends Command $invoice->calc()->getInvoice()->save(); $invoice->fresh(); // $invoice->service()->deletePdf()->save(); - if ($invoice->client->getSetting('enable_e_invoice')){ + if ($invoice->client->getSetting('enable_e_invoice')) { $invoice->service()->deleteEInvoice()->save(); } diff --git a/app/Console/Commands/SendTestEmails.php b/app/Console/Commands/SendTestEmails.php index 5a113e8f2f..9895355ac9 100644 --- a/app/Console/Commands/SendTestEmails.php +++ b/app/Console/Commands/SendTestEmails.php @@ -11,17 +11,10 @@ namespace App\Console\Commands; -use Faker\Factory; -use App\Models\User; -use App\Models\Account; -use App\Models\Company; -use App\Mail\TestMailServer; -use Illuminate\Console\Command; -use App\Jobs\Mail\NinjaMailerJob; -use App\DataMapper\CompanySettings; -use App\DataMapper\DefaultSettings; use App\Jobs\Mail\NinjaMailerObject; -use App\Mail\Migration\MaxCompanies; +use App\Mail\TestMailServer; +use App\Models\User; +use Illuminate\Console\Command; use Illuminate\Support\Facades\Mail; class SendTestEmails extends Command diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index c66cdc40e5..f67dc4af68 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -11,29 +11,29 @@ namespace App\Console; -use App\Utils\Ninja; -use App\Models\Account; -use App\Jobs\Ninja\QueueSize; -use App\Jobs\Util\DiskCleanup; -use App\Jobs\Util\ReminderJob; use App\Jobs\Cron\AutoBillCron; -use App\Jobs\Util\VersionCheck; -use App\Jobs\Ninja\TaskScheduler; -use App\Jobs\Util\SchedulerCheck; -use App\Jobs\Ninja\CheckACHStatus; -use App\Jobs\Cron\SubscriptionCron; -use App\Jobs\Ninja\AdjustEmailQuota; -use App\Jobs\Ninja\CompanySizeCheck; -use App\Jobs\Ninja\SystemMaintenance; -use App\Jobs\Quote\QuoteCheckExpired; -use App\Jobs\Util\UpdateExchangeRates; -use App\Jobs\Ninja\BankTransactionSync; use App\Jobs\Cron\RecurringExpensesCron; use App\Jobs\Cron\RecurringInvoicesCron; +use App\Jobs\Cron\SubscriptionCron; use App\Jobs\Cron\UpdateCalculatedFields; -use Illuminate\Console\Scheduling\Schedule; use App\Jobs\Invoice\InvoiceCheckLateWebhook; +use App\Jobs\Ninja\AdjustEmailQuota; +use App\Jobs\Ninja\BankTransactionSync; +use App\Jobs\Ninja\CheckACHStatus; +use App\Jobs\Ninja\CompanySizeCheck; +use App\Jobs\Ninja\QueueSize; +use App\Jobs\Ninja\SystemMaintenance; +use App\Jobs\Ninja\TaskScheduler; +use App\Jobs\Quote\QuoteCheckExpired; use App\Jobs\Subscription\CleanStaleInvoiceOrder; +use App\Jobs\Util\DiskCleanup; +use App\Jobs\Util\ReminderJob; +use App\Jobs\Util\SchedulerCheck; +use App\Jobs\Util\UpdateExchangeRates; +use App\Jobs\Util\VersionCheck; +use App\Models\Account; +use App\Utils\Ninja; +use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index bebf00b65d..814dc40383 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -481,14 +481,27 @@ class CompanySettings extends BaseSettings public $enable_e_invoice = false; - public $classification = ''; // individual, company, partnership, trust, charity, government, other + public $delivery_note_design_id = ''; + + public $statement_design_id = ''; + + public $payment_receipt_design_id = ''; + + public $payment_refund_design_id = ''; + + public $classification = ''; // individual, business, partnership, trust, charity, government, other public static $casts = [ - 'enable_e_invoice' => 'bool', + 'statement_design_id' => 'string', + 'delivery_note_design_id' => 'string', + 'payment_receipt_design_id' => 'string', + 'payment_refund_design_id' => 'string', + 'classification' => 'string', + 'enable_e_invoice' => 'bool', 'classification' => 'string', 'default_expense_payment_type_id' => 'string', - 'e_invoice_type' => 'string', - 'mailgun_endpoint' => 'string', + 'e_invoice_type' => 'string', + 'mailgun_endpoint' => 'string', 'client_initiated_payments' => 'bool', 'client_initiated_payments_minimum' => 'float', 'sync_invoice_quote_columns' => 'bool', @@ -768,6 +781,8 @@ class CompanySettings extends BaseSettings 'quote_design_id', 'credit_design_id', 'purchase_order_design_id', + 'statement_design_id', + 'delivery_note_design_id', ]; // /** @@ -999,6 +1014,15 @@ class CompanySettings extends BaseSettings '$total', '$credit.balance', ], + 'statement_details' => [ + '$statement_date', + '$balance' + ], + 'delivery_note_columns' => [ + '$product.item', + '$product.description', + '$product.quantity', + ], ]; return json_decode(json_encode($variables)); diff --git a/app/DataMapper/DefaultSettings.php b/app/DataMapper/DefaultSettings.php index 6451370cf6..e87fdf7993 100644 --- a/app/DataMapper/DefaultSettings.php +++ b/app/DataMapper/DefaultSettings.php @@ -34,4 +34,4 @@ class DefaultSettings extends BaseSettings ]; } -} \ No newline at end of file +} diff --git a/app/DataMapper/FreeCompanySettings.php b/app/DataMapper/FreeCompanySettings.php index 9866862a96..0ffe60f865 100644 --- a/app/DataMapper/FreeCompanySettings.php +++ b/app/DataMapper/FreeCompanySettings.php @@ -44,7 +44,7 @@ class FreeCompanySettings extends BaseSettings public $date_format_id = ''; -// public $enabled_item_tax_rates = 0; + // public $enabled_item_tax_rates = 0; public $expense_number_pattern = ''; public $expense_number_counter = 1; diff --git a/app/DataMapper/Settings/SettingsData.php b/app/DataMapper/Settings/SettingsData.php index b76379806f..2584a56540 100644 --- a/app/DataMapper/Settings/SettingsData.php +++ b/app/DataMapper/Settings/SettingsData.php @@ -10,7 +10,7 @@ */ namespace App\DataMapper\Settings; -class SettingsData +class SettingsData { public bool $auto_archive_invoice = false; // @implemented @@ -355,7 +355,7 @@ class SettingsData public string $email = ''; //@implemented - public string $country_id; //@implemented + public string $country_id = ''; //@implemented public string $vat_number = ''; //@implemented @@ -469,27 +469,28 @@ class SettingsData public function cast(mixed $object) { - if(is_array($object)) + if(is_array($object)) { $object = (object)$object; + } if (is_object($object)) { foreach ($object as $key => $value) { - try{ + try { settype($object->{$key}, gettype($this->{$key})); - } - catch(\Exception | \Error | \Throwable $e){ + } catch(\Exception | \Error | \Throwable $e) { - if(property_exists($this, $key)) + if(property_exists($this, $key)) { $object->{$key} = $this->{$key}; - else + } else { unset($object->{$key}); + } } // if(!property_exists($this, $key)) { // unset($object->{$key}); - // } + // } // elseif(is_array($object->{$key}) && gettype($this->{$key} != 'array')){ // $object->{$key} = $this->{$key}; // } @@ -512,4 +513,4 @@ class SettingsData { return (array)$this->object; } -} \ No newline at end of file +} diff --git a/app/DataMapper/Tax/BaseRule.php b/app/DataMapper/Tax/BaseRule.php index ba81697345..1888662326 100644 --- a/app/DataMapper/Tax/BaseRule.php +++ b/app/DataMapper/Tax/BaseRule.php @@ -11,11 +11,11 @@ namespace App\DataMapper\Tax; +use App\DataMapper\Tax\ZipTax\Response; +use App\DataProviders\USStates; use App\Models\Client; use App\Models\Invoice; use App\Models\Product; -use App\DataProviders\USStates; -use App\DataMapper\Tax\ZipTax\Response; class BaseRule implements RuleInterface { @@ -66,7 +66,7 @@ class BaseRule implements RuleInterface 'SK', // Slovakia ]; - public array $region_codes = [ + public array $region_codes = [ 'AT' => 'EU', // Austria 'BE' => 'EU', // Belgium 'BG' => 'EU', // Bulgaria @@ -147,8 +147,9 @@ class BaseRule implements RuleInterface $this->resolveRegions(); - if(!$this->isTaxableRegion()) + if(!$this->isTaxableRegion()) { return $this; + } $this->configTaxData(); @@ -173,26 +174,26 @@ class BaseRule implements RuleInterface /** Harvest the client_region */ /** If the tax data is already set and the invoice is marked as sent, do not adjust the rates */ - if($this->invoice->tax_data && $this->invoice->status_id > 1) + if($this->invoice->tax_data && $this->invoice->status_id > 1) { return $this; + } /** * Origin - Company Tax Data * Destination - Client Tax Data - * + * */ $tax_data = false; - if($this->seller_region == 'US' && $this->client_region == 'US'){ + if($this->seller_region == 'US' && $this->client_region == 'US') { $company = $this->invoice->company; /** If no company tax data has been configured, lets do that now. */ /** We should never encounter this scenario */ - if(!$company->origin_tax_data) - { - $this->should_calc_tax = false; + if(!$company->origin_tax_data) { + $this->should_calc_tax = false; return $this; } @@ -201,8 +202,7 @@ class BaseRule implements RuleInterface $tax_data = $company->origin_tax_data; - } - elseif($this->client->tax_data){ + } elseif($this->client->tax_data) { $tax_data = $this->client->tax_data; @@ -215,8 +215,9 @@ class BaseRule implements RuleInterface $this->invoice->tax_data = $tax_data; - if(\DB::transactionLevel() == 0) + if(\DB::transactionLevel() == 0) { $this->invoice->saveQuietly(); + } } return $this; @@ -234,7 +235,7 @@ class BaseRule implements RuleInterface $this->client_region = $this->region_codes[$this->client->country->iso_3166_2]; - match($this->client_region){ + match($this->client_region) { 'US' => $this->client_subregion = isset($this->invoice?->client?->tax_data?->geoState) ? $this->invoice->client->tax_data->geoState : $this->getUSState(), 'EU' => $this->client_subregion = $this->client->country->iso_3166_2, 'AU' => $this->client_subregion = 'AU', @@ -251,8 +252,9 @@ class BaseRule implements RuleInterface $states = USStates::$states; - if(isset($states[$this->client->state])) + if(isset($states[$this->client->state])) { return $this->client->state; + } return USStates::getState(strlen($this->client->postal_code) > 1 ? $this->client->postal_code : $this->client->shipping_postal_code); @@ -263,7 +265,7 @@ class BaseRule implements RuleInterface public function isTaxableRegion(): bool { - return $this->client->company->tax_data->regions->{$this->client_region}->tax_all_subregions || + return $this->client->company->tax_data->regions->{$this->client_region}->tax_all_subregions || (property_exists($this->client->company->tax_data->regions->{$this->client_region}->subregions, $this->client_subregion) && $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->apply_tax); } @@ -277,8 +279,7 @@ class BaseRule implements RuleInterface return $this; - } - elseif($this->client_region == 'AU'){ //these are defaults and are only stubbed out for now, for AU we can actually remove these + } elseif($this->client_region == 'AU') { //these are defaults and are only stubbed out for now, for AU we can actually remove these $this->tax_rate1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_rate; $this->tax_name1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_name; diff --git a/app/DataMapper/Tax/DE/Rule.php b/app/DataMapper/Tax/DE/Rule.php index 8214188c36..5296674618 100644 --- a/app/DataMapper/Tax/DE/Rule.php +++ b/app/DataMapper/Tax/DE/Rule.php @@ -11,12 +11,12 @@ namespace App\DataMapper\Tax\DE; -use App\Models\Product; use App\DataMapper\Tax\BaseRule; use App\DataMapper\Tax\RuleInterface; +use App\Models\Product; class Rule extends BaseRule implements RuleInterface -{ +{ /** @var string $seller_region */ public string $seller_region = 'EU'; @@ -67,7 +67,7 @@ class Rule extends BaseRule implements RuleInterface return $this->taxExempt($item); } - match(intval($item->tax_id)){ + match(intval($item->tax_id)) { Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt($item), Product::PRODUCT_TYPE_DIGITAL => $this->taxDigital($item), Product::PRODUCT_TYPE_SERVICE => $this->taxService($item), @@ -220,39 +220,28 @@ class Rule extends BaseRule implements RuleInterface // nlog("tax exempt"); $this->tax_rate = 0; $this->reduced_tax_rate = 0; - } - elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->vat_number && $this->eu_business_tax_exempt) - // elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt) - { + } elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->vat_number && $this->eu_business_tax_exempt) { + // elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt) // nlog("euro zone and tax exempt"); $this->tax_rate = 0; $this->reduced_tax_rate = 0; - } - elseif(!in_array($this->client_subregion, $this->eu_country_codes) && ($this->foreign_consumer_tax_exempt || $this->foreign_business_tax_exempt)) //foreign + tax exempt - { + } elseif(!in_array($this->client_subregion, $this->eu_country_codes) && ($this->foreign_consumer_tax_exempt || $this->foreign_business_tax_exempt)) { //foreign + tax exempt // nlog("foreign and tax exempt"); $this->tax_rate = 0; $this->reduced_tax_rate = 0; - } - elseif(!in_array($this->client_subregion, $this->eu_country_codes)) - { + } elseif(!in_array($this->client_subregion, $this->eu_country_codes)) { $this->defaultForeign(); - } - elseif(in_array($this->client_subregion, $this->eu_country_codes) && !$this->client->vat_number) //eu country / no valid vat - { - if(($this->client->company->tax_data->seller_subregion != $this->client_subregion) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold) - { + } elseif(in_array($this->client_subregion, $this->eu_country_codes) && !$this->client->vat_number) { //eu country / no valid vat + if(($this->client->company->tax_data->seller_subregion != $this->client_subregion) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold) { // nlog("eu zone with sales above threshold"); $this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate; $this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate; - } - else { + } else { // nlog("EU with intra-community supply ie DE to DE"); $this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate; $this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate; } - } - else { + } else { // nlog("default tax"); $this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate; $this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate; @@ -262,4 +251,4 @@ class Rule extends BaseRule implements RuleInterface } -} \ No newline at end of file +} diff --git a/app/DataMapper/Tax/RuleInterface.php b/app/DataMapper/Tax/RuleInterface.php index e4ff2c0e2d..73994de722 100644 --- a/app/DataMapper/Tax/RuleInterface.php +++ b/app/DataMapper/Tax/RuleInterface.php @@ -36,4 +36,4 @@ interface RuleInterface public function override($item); public function calculateRates(); -} \ No newline at end of file +} diff --git a/app/DataMapper/Tax/TaxData.php b/app/DataMapper/Tax/TaxData.php index c1696ef2a4..945a3d0a46 100644 --- a/app/DataMapper/Tax/TaxData.php +++ b/app/DataMapper/Tax/TaxData.php @@ -15,7 +15,7 @@ use App\DataMapper\Tax\ZipTax\Response; /** * InvoiceTaxData - * + * * Definition for the invoice tax data structure */ class TaxData diff --git a/app/DataMapper/Tax/TaxModel.php b/app/DataMapper/Tax/TaxModel.php index 8fd686e88f..ca6d41a3f4 100644 --- a/app/DataMapper/Tax/TaxModel.php +++ b/app/DataMapper/Tax/TaxModel.php @@ -11,7 +11,7 @@ namespace App\DataMapper\Tax; -class TaxModel +class TaxModel { /** @var string $seller_subregion */ @@ -32,10 +32,11 @@ class TaxModel public function __construct(public ?TaxModel $model = null) { - if(!$this->model) + if(!$this->model) { $this->regions = $this->init(); - else + } else { $this->regions = $model; + } } @@ -79,7 +80,7 @@ class TaxModel * * @return self */ - private function auSubRegions(): self + private function auSubRegions(): self { $this->regions->AU->subregions = new \stdClass(); @@ -387,7 +388,7 @@ class TaxModel $this->regions->EU->subregions->EE = new \stdClass(); $this->regions->EU->subregions->EE->tax_rate = 20; - $this->regions->EU->subregions->EE->tax_name = 'KM'; + $this->regions->EU->subregions->EE->tax_name = 'KM'; $this->regions->EU->subregions->EE->reduced_tax_rate = 9; $this->regions->EU->subregions->EE->apply_tax = false; diff --git a/app/DataMapper/Tax/US/Rule.php b/app/DataMapper/Tax/US/Rule.php index e880027201..0a7179113b 100644 --- a/app/DataMapper/Tax/US/Rule.php +++ b/app/DataMapper/Tax/US/Rule.php @@ -74,7 +74,7 @@ class Rule extends BaseRule implements RuleInterface Product::PRODUCT_TYPE_SHIPPING => $this->taxShipping($item), Product::PRODUCT_TYPE_PHYSICAL => $this->taxPhysical($item), Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced($item), - Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override($item), + Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override($item), Product::PRODUCT_TYPE_ZERO_RATED => $this->zeroRated($item), default => $this->default($item), }; @@ -117,10 +117,9 @@ class Rule extends BaseRule implements RuleInterface */ public function taxService($item): self { - if(in_array($this->tax_data?->txbService,['Y','L'])) { + if(in_array($this->tax_data?->txbService, ['Y','L'])) { $this->default($item); - } - else { + } else { $this->taxExempt($item); } @@ -224,4 +223,4 @@ class Rule extends BaseRule implements RuleInterface return $this; } -} \ No newline at end of file +} diff --git a/app/DataMapper/Tax/ZipTax/Response.php b/app/DataMapper/Tax/ZipTax/Response.php index 4a8e036343..a64f275402 100644 --- a/app/DataMapper/Tax/ZipTax/Response.php +++ b/app/DataMapper/Tax/ZipTax/Response.php @@ -53,7 +53,7 @@ class Response * "district5SalesTax" => 0, * "district5UseTax" => 0, * "originDestination" => "D", - * + * * ]; * */ @@ -114,4 +114,3 @@ class Response } } - diff --git a/app/DataProviders/USStates.php b/app/DataProviders/USStates.php index 4809df8439..75c2059786 100644 --- a/app/DataProviders/USStates.php +++ b/app/DataProviders/USStates.php @@ -33868,18 +33868,21 @@ class USStates public static function getState(?string $zip = '90210'): string { - if(isset(self::$zip_code_map[$zip])) + if(isset(self::$zip_code_map[$zip])) { return self::$zip_code_map[$zip]; + } $prefix_state = self::getStateFromThreeDigitPrefix($zip); - if($prefix_state) + if($prefix_state) { return $prefix_state; + } $zippo_response = self::getStateFromZippo($zip); - if($zippo_response) + if($zippo_response) { return $zippo_response; + } throw new \Exception('Zip code not found'); } @@ -33905,8 +33908,9 @@ class USStates $response = Http::get("https://api.zippopotam.us/us/{$zip}"); - if($response->failed()) + if($response->failed()) { return false; + } $data = $response->object(); @@ -33921,7 +33925,7 @@ class USStates public static function getStateFromThreeDigitPrefix($zip): mixed { - /* 000 to 999 */ + /* 000 to 999 */ $zip_by_state = [ '--', '--', '--', '--', '--', 'NY', 'PR', 'PR', 'VI', 'PR', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', 'MA', @@ -34004,7 +34008,7 @@ class USStates $prefix = substr($zip, 0, 3); $index = intval($prefix); - /* converts prefix to integer */ + /* converts prefix to integer */ return $zip_by_state[$index] == "--" ? false : $zip_by_state[$index]; } diff --git a/app/Events/Account/AccountCreated.php b/app/Events/Account/AccountCreated.php index 0761cdf4b9..4cd6d46ee0 100644 --- a/app/Events/Account/AccountCreated.php +++ b/app/Events/Account/AccountCreated.php @@ -49,9 +49,9 @@ class AccountCreated // * // * @return Channel|array // */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - // return new PrivateChannel('channel-name'); - } + // return new PrivateChannel('channel-name'); + } } diff --git a/app/Events/Account/StripeConnectFailure.php b/app/Events/Account/StripeConnectFailure.php index fd6f5a5d57..ebe501512b 100644 --- a/app/Events/Account/StripeConnectFailure.php +++ b/app/Events/Account/StripeConnectFailure.php @@ -12,11 +12,9 @@ namespace App\Events\Account; use App\Models\Company; -use Illuminate\Broadcasting\Channel; -use Illuminate\Queue\SerializesModels; -use Illuminate\Broadcasting\PrivateChannel; -use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Queue\SerializesModels; /** * Class StripeConnectFailure. diff --git a/app/Events/Client/ClientWasArchived.php b/app/Events/Client/ClientWasArchived.php index aca000b8e5..46aac9cba8 100644 --- a/app/Events/Client/ClientWasArchived.php +++ b/app/Events/Client/ClientWasArchived.php @@ -15,7 +15,6 @@ use App\Models\Client; use App\Models\Company; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -54,8 +53,8 @@ class ClientWasArchived // * // * @return Channel|array // */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Company/CompanyDocumentsDeleted.php b/app/Events/Company/CompanyDocumentsDeleted.php index 2c8f11c4f2..831a4958d1 100644 --- a/app/Events/Company/CompanyDocumentsDeleted.php +++ b/app/Events/Company/CompanyDocumentsDeleted.php @@ -14,7 +14,6 @@ namespace App\Events\Company; use App\Models\Company; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -42,8 +41,8 @@ class CompanyDocumentsDeleted * * @return Channel|array */ - public function broadcastOn() - { -return []; - } + public function broadcastOn() + { + return []; + } } diff --git a/app/Events/Contact/ContactLoggedIn.php b/app/Events/Contact/ContactLoggedIn.php index 0e98a54449..e2fa77103f 100644 --- a/app/Events/Contact/ContactLoggedIn.php +++ b/app/Events/Contact/ContactLoggedIn.php @@ -14,7 +14,6 @@ namespace App\Events\Contact; use App\Models\ClientContact; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -50,8 +49,8 @@ class ContactLoggedIn * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Design/DesignWasArchived.php b/app/Events/Design/DesignWasArchived.php index 1dd9105c7c..a3745552b2 100644 --- a/app/Events/Design/DesignWasArchived.php +++ b/app/Events/Design/DesignWasArchived.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\Design; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -35,8 +34,8 @@ class DesignWasArchived * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Design/DesignWasCreated.php b/app/Events/Design/DesignWasCreated.php index 213eb98824..7cbf9aeec7 100644 --- a/app/Events/Design/DesignWasCreated.php +++ b/app/Events/Design/DesignWasCreated.php @@ -11,10 +11,10 @@ namespace App\Events\Design; -use App\Models\Design; use App\Models\Company; -use Illuminate\Queue\SerializesModels; +use App\Models\Design; use Illuminate\Broadcasting\PrivateChannel; +use Illuminate\Queue\SerializesModels; /** * Class DesignWasCreated. @@ -32,8 +32,8 @@ class DesignWasCreated * * @return PrivateChannel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Design/DesignWasDeleted.php b/app/Events/Design/DesignWasDeleted.php index d9142724a0..fe21e18646 100644 --- a/app/Events/Design/DesignWasDeleted.php +++ b/app/Events/Design/DesignWasDeleted.php @@ -11,10 +11,10 @@ namespace App\Events\Design; -use App\Models\Design; use App\Models\Company; -use Illuminate\Queue\SerializesModels; +use App\Models\Design; use Illuminate\Broadcasting\PrivateChannel; +use Illuminate\Queue\SerializesModels; /** * Class DesignWasDeleted. @@ -32,8 +32,8 @@ class DesignWasDeleted * * @return PrivateChannel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Design/DesignWasRestored.php b/app/Events/Design/DesignWasRestored.php index 6daa2c2545..c237d1f2c9 100644 --- a/app/Events/Design/DesignWasRestored.php +++ b/app/Events/Design/DesignWasRestored.php @@ -11,10 +11,10 @@ namespace App\Events\Design; -use App\Models\Design; use App\Models\Company; -use Illuminate\Queue\SerializesModels; +use App\Models\Design; use Illuminate\Broadcasting\PrivateChannel; +use Illuminate\Queue\SerializesModels; /** * Class DesignWasRestored. @@ -32,8 +32,8 @@ class DesignWasRestored * * @return PrivateChannel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Design/DesignWasUpdated.php b/app/Events/Design/DesignWasUpdated.php index 3b215fdff2..bf18bd88cf 100644 --- a/app/Events/Design/DesignWasUpdated.php +++ b/app/Events/Design/DesignWasUpdated.php @@ -11,10 +11,10 @@ namespace App\Events\Design; -use App\Models\Design; use App\Models\Company; -use Illuminate\Queue\SerializesModels; +use App\Models\Design; use Illuminate\Broadcasting\PrivateChannel; +use Illuminate\Queue\SerializesModels; /** * Class DesignWasUpdated. @@ -32,8 +32,8 @@ class DesignWasUpdated * * @return PrivateChannel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Document/DocumentWasArchived.php b/app/Events/Document/DocumentWasArchived.php index 229e7d6c16..edfa4bea85 100644 --- a/app/Events/Document/DocumentWasArchived.php +++ b/app/Events/Document/DocumentWasArchived.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\Document; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; diff --git a/app/Events/Payment/Methods/MethodDeleted.php b/app/Events/Payment/Methods/MethodDeleted.php index 5e80e20f8a..f205d872c8 100644 --- a/app/Events/Payment/Methods/MethodDeleted.php +++ b/app/Events/Payment/Methods/MethodDeleted.php @@ -15,7 +15,6 @@ use App\Models\ClientGatewayToken; use App\Models\Company; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -51,8 +50,8 @@ class MethodDeleted * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Payment/PaymentWasEmailed.php b/app/Events/Payment/PaymentWasEmailed.php index 284d52de48..767918ab03 100644 --- a/app/Events/Payment/PaymentWasEmailed.php +++ b/app/Events/Payment/PaymentWasEmailed.php @@ -11,12 +11,12 @@ namespace App\Events\Payment; +use App\Models\ClientContact; use App\Models\Company; use App\Models\Payment; -use App\Models\ClientContact; -use Illuminate\Queue\SerializesModels; -use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Queue\SerializesModels; /** * Class PaymentWasEmailed. diff --git a/app/Events/PurchaseOrder/PurchaseOrderWasViewed.php b/app/Events/PurchaseOrder/PurchaseOrderWasViewed.php index a144639a68..c9555bd90c 100644 --- a/app/Events/PurchaseOrder/PurchaseOrderWasViewed.php +++ b/app/Events/PurchaseOrder/PurchaseOrderWasViewed.php @@ -12,7 +12,6 @@ namespace App\Events\PurchaseOrder; use App\Models\Company; -use App\Models\PurchaseOrder; use App\Models\PurchaseOrderInvitation; use Illuminate\Queue\SerializesModels; diff --git a/app/Events/Quote/QuoteWasEmailed.php b/app/Events/Quote/QuoteWasEmailed.php index 5792167c42..ef8055edd4 100644 --- a/app/Events/Quote/QuoteWasEmailed.php +++ b/app/Events/Quote/QuoteWasEmailed.php @@ -12,7 +12,6 @@ namespace App\Events\Quote; use App\Models\Company; -use App\Models\Quote; use App\Models\QuoteInvitation; use Illuminate\Queue\SerializesModels; diff --git a/app/Events/Subscription/SubscriptionWasCreated.php b/app/Events/Subscription/SubscriptionWasCreated.php index 9d1616defb..fff93b1507 100644 --- a/app/Events/Subscription/SubscriptionWasCreated.php +++ b/app/Events/Subscription/SubscriptionWasCreated.php @@ -5,7 +5,6 @@ namespace App\Events\Subscription; use App\Models\Company; use App\Models\Subscription; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -45,8 +44,8 @@ class SubscriptionWasCreated * * @return \Illuminate\Broadcasting\Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/User/UserLoggedIn.php b/app/Events/User/UserLoggedIn.php index f3b55c2a1c..bddb7104ec 100644 --- a/app/Events/User/UserLoggedIn.php +++ b/app/Events/User/UserLoggedIn.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -35,8 +34,8 @@ class UserLoggedIn * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/User/UserWasArchived.php b/app/Events/User/UserWasArchived.php index 51657baffb..cb7077668f 100644 --- a/app/Events/User/UserWasArchived.php +++ b/app/Events/User/UserWasArchived.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -35,8 +34,8 @@ class UserWasArchived * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/User/UserWasCreated.php b/app/Events/User/UserWasCreated.php index c4bba87846..5d30fa5261 100644 --- a/app/Events/User/UserWasCreated.php +++ b/app/Events/User/UserWasCreated.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -35,8 +34,8 @@ class UserWasCreated * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/User/UserWasDeleted.php b/app/Events/User/UserWasDeleted.php index cae639e208..d7323d78d5 100644 --- a/app/Events/User/UserWasDeleted.php +++ b/app/Events/User/UserWasDeleted.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -54,8 +53,8 @@ class UserWasDeleted * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/User/UserWasRestored.php b/app/Events/User/UserWasRestored.php index 2d722fd189..196a73e451 100644 --- a/app/Events/User/UserWasRestored.php +++ b/app/Events/User/UserWasRestored.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -54,8 +53,8 @@ class UserWasRestored * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/User/UserWasUpdated.php b/app/Events/User/UserWasUpdated.php index a4eda9752c..ef495814a7 100644 --- a/app/Events/User/UserWasUpdated.php +++ b/app/Events/User/UserWasUpdated.php @@ -15,7 +15,6 @@ use App\Models\Company; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; @@ -54,8 +53,8 @@ class UserWasUpdated * * @return Channel|array */ - public function broadcastOn() - { + public function broadcastOn() + { return []; - } + } } diff --git a/app/Events/Vendor/VendorContactLoggedIn.php b/app/Events/Vendor/VendorContactLoggedIn.php index 2422af1023..9a0ddad948 100644 --- a/app/Events/Vendor/VendorContactLoggedIn.php +++ b/app/Events/Vendor/VendorContactLoggedIn.php @@ -14,9 +14,9 @@ namespace App\Events\Vendor; use App\Models\Company; use App\Models\VendorContact; use Illuminate\Broadcasting\Channel; -use Illuminate\Queue\SerializesModels; -use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Queue\SerializesModels; /** * Class VendorContactLoggedIn. diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 4e8f339a39..e993581e5a 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -11,31 +11,31 @@ namespace App\Exceptions; -use Throwable; -use PDOException; use App\Utils\Ninja; -use Sentry\State\Scope; -use Illuminate\Support\Arr; -use Illuminate\Http\Request; -use InvalidArgumentException; -use Sentry\Laravel\Integration; -use Illuminate\Support\Facades\Schema; use Aws\Exception\CredentialsException; use GuzzleHttp\Exception\ConnectException; -use Illuminate\Auth\AuthenticationException; -use League\Flysystem\UnableToCreateDirectory; -use Illuminate\Session\TokenMismatchException; -use Illuminate\Validation\ValidationException; use Illuminate\Auth\Access\AuthorizationException; -use Illuminate\Queue\MaxAttemptsExceededException; -use Illuminate\Http\Exceptions\ThrottleRequestsException; -use Symfony\Component\Process\Exception\RuntimeException; +use Illuminate\Auth\AuthenticationException; +use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; use Illuminate\Database\Eloquent\RelationNotFoundException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Illuminate\Http\Exceptions\ThrottleRequestsException; +use Illuminate\Http\Request; +use Illuminate\Queue\MaxAttemptsExceededException; +use Illuminate\Session\TokenMismatchException; +use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Schema; +use Illuminate\Validation\ValidationException; +use InvalidArgumentException; +use League\Flysystem\UnableToCreateDirectory; +use PDOException; +use Sentry\Laravel\Integration; +use Sentry\State\Scope; use Symfony\Component\Console\Exception\CommandNotFoundException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Process\Exception\RuntimeException; +use Throwable; class Handler extends ExceptionHandler { @@ -223,8 +223,8 @@ class Handler extends ExceptionHandler return response()->json(['message' => $exception->getMessage()], 500); } elseif ($exception instanceof ThrottleRequestsException && $request->expectsJson()) { return response()->json(['message'=>'Too many requests'], 429); - // } elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) { - // return response()->json(['message'=>'Fatal error'], 500); //@deprecated + // } elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) { + // return response()->json(['message'=>'Fatal error'], 500); //@deprecated } elseif ($exception instanceof AuthorizationException && $request->expectsJson()) { return response()->json(['message'=> $exception->getMessage()], 401); } elseif ($exception instanceof TokenMismatchException) { diff --git a/app/Exceptions/PaymentRefundFailed.php b/app/Exceptions/PaymentRefundFailed.php index 28e00858e8..9ba3a922fb 100644 --- a/app/Exceptions/PaymentRefundFailed.php +++ b/app/Exceptions/PaymentRefundFailed.php @@ -13,8 +13,8 @@ namespace App\Exceptions; use Exception; -use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; class PaymentRefundFailed extends Exception { diff --git a/app/Exceptions/QuoteConversion.php b/app/Exceptions/QuoteConversion.php index ceafdf8b49..a2e11e6374 100644 --- a/app/Exceptions/QuoteConversion.php +++ b/app/Exceptions/QuoteConversion.php @@ -13,8 +13,8 @@ namespace App\Exceptions; use Exception; -use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; class QuoteConversion extends Exception { diff --git a/app/Exceptions/YodleeApiException.php b/app/Exceptions/YodleeApiException.php index b56eedced3..c8150d18cb 100644 --- a/app/Exceptions/YodleeApiException.php +++ b/app/Exceptions/YodleeApiException.php @@ -13,8 +13,8 @@ namespace App\Exceptions; use Exception; -use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; class YodleeApiException extends Exception { diff --git a/app/Export/CSV/ActivityExport.php b/app/Export/CSV/ActivityExport.php index 3cd1c89632..e738f6371a 100644 --- a/app/Export/CSV/ActivityExport.php +++ b/app/Export/CSV/ActivityExport.php @@ -11,17 +11,17 @@ namespace App\Export\CSV; -use App\Models\Task; -use App\Utils\Ninja; -use League\Csv\Writer; -use App\Models\Company; -use App\Models\Activity; use App\Libraries\MultiDB; +use App\Models\Activity; +use App\Models\Company; use App\Models\DateFormat; +use App\Models\Task; +use App\Transformers\ActivityTransformer; +use App\Utils\Ninja; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; -use Illuminate\Database\Eloquent\Builder; -use App\Transformers\ActivityTransformer; +use League\Csv\Writer; class ActivityExport extends BaseExport { @@ -53,44 +53,44 @@ class ActivityExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); - $report = $query->cursor() - ->map(function ($resource) { - $row = $this->buildActivityRow($resource); - return $this->processMetaData($row, $resource); - })->toArray(); + $report = $query->cursor() + ->map(function ($resource) { + $row = $this->buildActivityRow($resource); + return $this->processMetaData($row, $resource); + })->toArray(); return array_merge(['columns' => $header], $report); } private function buildActivityRow(Activity $activity): array { - return [ - Carbon::parse($activity->created_at)->format($this->date_format), - ctrans("texts.activity_{$activity->activity_type_id}",[ - 'payment_amount' => $activity->payment ? $activity->payment->amount : '', - 'adjustment' => $activity->payment ? $activity->payment->refunded : '', - 'client' => $activity->client ? $activity->client->present()->name() : '', - 'contact' => $activity->contact ? $activity->contact->present()->name() : '', - 'quote' => $activity->quote ? $activity->quote->number : '', - 'user' => $activity->user ? $activity->user->present()->name() : 'System', - 'expense' => $activity->expense ? $activity->expense->number : '', - 'invoice' => $activity->invoice ? $activity->invoice->number : '', - 'recurring_invoice' => $activity->recurring_invoice ? $activity->recurring_invoice->number : '', - 'payment' => $activity->payment ? $activity->payment->number : '', - 'credit' => $activity->credit ? $activity->credit->number : '', - 'task' => $activity->task ? $activity->task->number : '', - 'vendor' => $activity->vendor ? $activity->vendor->present()->name() : '', - 'purchase_order' => $activity->purchase_order ? $activity->purchase_order->number : '', - 'subscription' => $activity->subscription ? $activity->subscription->name : '', - 'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact->present()->name() : '', - 'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense->number : '', - ]), - $activity->ip, + return [ + Carbon::parse($activity->created_at)->format($this->date_format), + ctrans("texts.activity_{$activity->activity_type_id}", [ + 'payment_amount' => $activity->payment ? $activity->payment->amount : '', + 'adjustment' => $activity->payment ? $activity->payment->refunded : '', + 'client' => $activity->client ? $activity->client->present()->name() : '', + 'contact' => $activity->contact ? $activity->contact->present()->name() : '', + 'quote' => $activity->quote ? $activity->quote->number : '', + 'user' => $activity->user ? $activity->user->present()->name() : 'System', + 'expense' => $activity->expense ? $activity->expense->number : '', + 'invoice' => $activity->invoice ? $activity->invoice->number : '', + 'recurring_invoice' => $activity->recurring_invoice ? $activity->recurring_invoice->number : '', + 'payment' => $activity->payment ? $activity->payment->number : '', + 'credit' => $activity->credit ? $activity->credit->number : '', + 'task' => $activity->task ? $activity->task->number : '', + 'vendor' => $activity->vendor ? $activity->vendor->present()->name() : '', + 'purchase_order' => $activity->purchase_order ? $activity->purchase_order->number : '', + 'subscription' => $activity->subscription ? $activity->subscription->name : '', + 'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact->present()->name() : '', + 'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense->number : '', + ]), + $activity->ip, ]; } @@ -169,6 +169,6 @@ class ActivityExport extends BaseExport } return $clean_row; - } + } } diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index fa6ab80ef3..74474b98c7 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -11,30 +11,28 @@ namespace App\Export\CSV; -use App\Models\Activity; -use App\Models\Quote; -use App\Utils\Number; use App\Models\Client; -use App\Models\Credit; -use App\Utils\Helpers; +use App\Models\ClientContact; use App\Models\Company; +use App\Models\Credit; +use App\Models\Document; use App\Models\Expense; use App\Models\Invoice; use App\Models\Payment; -use App\Models\Document; -use League\Fractal\Manager; -use App\Models\ClientContact; -use App\Models\PurchaseOrder; -use App\Models\RecurringInvoice; -use Illuminate\Support\Carbon; -use App\Utils\Traits\MakesHash; -use App\Transformers\TaskTransformer; -use App\Transformers\PaymentTransformer; -use Illuminate\Database\Eloquent\Builder; -use League\Fractal\Serializer\ArraySerializer; use App\Models\Product; +use App\Models\PurchaseOrder; +use App\Models\Quote; +use App\Models\RecurringInvoice; use App\Models\Task; use App\Models\Vendor; +use App\Transformers\PaymentTransformer; +use App\Transformers\TaskTransformer; +use App\Utils\Helpers; +use App\Utils\Traits\MakesHash; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Carbon; +use League\Fractal\Manager; +use League\Fractal\Serializer\ArraySerializer; class BaseExport { @@ -172,7 +170,7 @@ class BaseExport 'recurring_invoice' => 'invoice.recurring_id', ]; - protected array $recurring_invoice_report_keys = [ + protected array $recurring_invoice_report_keys = [ "invoice_number" => "recurring_invoice.number", "amount" => "recurring_invoice.amount", "balance" => "recurring_invoice.balance", @@ -446,8 +444,7 @@ class BaseExport $client = Client::withTrashed()->find($this->input['client_id']); $this->client_description = $client->present()->name; return $query->where('client_id', $this->input['client_id']); - } - elseif(isset($this->input['clients']) && count($this->input['clients']) > 0) { + } elseif(isset($this->input['clients']) && count($this->input['clients']) > 0) { $this->client_description = 'Multiple Clients'; return $query->whereIn('client_id', $this->input['clients']); @@ -459,8 +456,9 @@ class BaseExport { $parts = explode(".", $key); - if(!is_array($parts) || count($parts) < 2) + if(!is_array($parts) || count($parts) < 2) { return ''; + } $value = ''; @@ -497,8 +495,9 @@ class BaseExport private function resolveVendorContactKey($column, $entity, $transformer) { - if(!$entity->vendor) + if(!$entity->vendor) { return ""; + } $primary_contact = $entity->vendor->primary_contact()->first() ?? $entity->vendor->contacts()->first(); @@ -510,18 +509,21 @@ class BaseExport private function resolveExpenseKey($column, $entity, $transformer) { - if($column == 'user' && $entity?->expense?->user) + if($column == 'user' && $entity?->expense?->user) { return $entity->expense->user->present()->name() ?? ' '; + } - if($column == 'assigned_user' && $entity?->expense?->assigned_user) + if($column == 'assigned_user' && $entity?->expense?->assigned_user) { return $entity->expense->assigned_user->present()->name() ?? ' '; + } if($column == 'category' && $entity->expense) { return $entity->expense->category?->name ?? ' '; } - if($entity instanceof Expense) + if($entity instanceof Expense) { return ''; + } $transformed_entity = $transformer->includeExpense($entity); @@ -529,11 +531,13 @@ class BaseExport $manager->setSerializer(new ArraySerializer()); $transformed_entity = $manager->createData($transformed_entity)->toArray(); - if(array_key_exists($column, $transformed_entity)) - return $transformed_entity[$column]; + if(array_key_exists($column, $transformed_entity)) { + return $transformed_entity[$column]; + } - if(property_exists($entity, $column)) + if(property_exists($entity, $column)) { return $entity?->{$column} ?? ''; + } nlog("export: Could not resolve expense key: {$column}"); @@ -560,8 +564,9 @@ class BaseExport private function resolveVendorKey($column, $entity, $transformer) { - if(!$entity->vendor) + if(!$entity->vendor) { return ''; + } $transformed_entity = $transformer->includeVendor($entity); @@ -569,24 +574,29 @@ class BaseExport $manager->setSerializer(new ArraySerializer()); $transformed_entity = $manager->createData($transformed_entity)->toArray(); - if($column == 'name') + if($column == 'name') { return $entity->vendor->present()->name() ?: ''; + } - if($column == 'user_id') + if($column == 'user_id') { return $entity->vendor->user->present()->name() ?: ''; + } - if($column == 'country_id') + if($column == 'country_id') { return $entity->vendor->country ? ctrans("texts.country_{$entity->vendor->country->name}") : ''; + } if ($column == 'currency_id') { return $entity->vendor->currency() ? $entity->vendor->currency()->code : $entity->company->currency()->code; } - if($column == 'status') + if($column == 'status') { return $entity->stringStatus($entity->status_id) ?: ''; + } - if(array_key_exists($column, $transformed_entity)) + if(array_key_exists($column, $transformed_entity)) { return $transformed_entity[$column]; + } // nlog("export: Could not resolve vendor key: {$column}"); @@ -598,8 +608,9 @@ class BaseExport private function resolveClientKey($column, $entity, $transformer) { - if(!$entity->client) + if(!$entity->client) { return ''; + } $transformed_client = $transformer->includeClient($entity); @@ -607,36 +618,46 @@ class BaseExport $manager->setSerializer(new ArraySerializer()); $transformed_client = $manager->createData($transformed_client)->toArray(); - if(in_array($column, ['client.name', 'name'])) + if(in_array($column, ['client.name', 'name'])) { return $transformed_client['display_name']; + } - if(in_array($column, ['client.user_id', 'user_id'])) + if(in_array($column, ['client.user_id', 'user_id'])) { return $entity->client->user->present()->name(); + } - if(in_array($column, ['client.assigned_user_id', 'assigned_user_id'])) + if(in_array($column, ['client.assigned_user_id', 'assigned_user_id'])) { return $entity->client->assigned_user->present()->name(); + } - if(in_array($column, ['client.country_id', 'country_id'])) + if(in_array($column, ['client.country_id', 'country_id'])) { return $entity->client->country ? ctrans("texts.country_{$entity->client->country->name}") : ''; + } - if(in_array($column, ['client.shipping_country_id', 'shipping_country_id'])) + if(in_array($column, ['client.shipping_country_id', 'shipping_country_id'])) { return $entity->client->shipping_country ? ctrans("texts.country_{$entity->client->shipping_country->name}") : ''; + } - if(in_array($column, ['client.size_id', 'size_id'])) + if(in_array($column, ['client.size_id', 'size_id'])) { return $entity->client->size?->name ?? ''; + } - if(in_array($column, ['client.industry_id', 'industry_id'])) + if(in_array($column, ['client.industry_id', 'industry_id'])) { return $entity->client->industry?->name ?? ''; + } - if (in_array($column, ['client.currency_id', 'currency_id'])) + if (in_array($column, ['client.currency_id', 'currency_id'])) { return $entity->client->currency() ? $entity->client->currency()->code : $entity->company->currency()->code; + } - if(in_array($column, ['payment_terms', 'client.payment_terms'])) + if(in_array($column, ['payment_terms', 'client.payment_terms'])) { return $entity->client->getSetting('payment_terms'); + } - if(array_key_exists($column, $transformed_client)) + if(array_key_exists($column, $transformed_client)) { return $transformed_client[$column]; + } // nlog("export: Could not resolve client key: {$column}"); @@ -650,8 +671,9 @@ class BaseExport $transformed_entity = $transformer->transform($entity); - if($column == 'status') + if($column == 'status') { return $entity->stringStatus($entity->status_id); + } return ''; } @@ -682,16 +704,19 @@ class BaseExport $manager->setSerializer(new ArraySerializer()); $transformed_invoices = $manager->createData($transformed_invoices)->toArray(); - if(!isset($transformed_invoices['App\\Models\\Invoice'])) + if(!isset($transformed_invoices['App\\Models\\Invoice'])) { return ''; + } $transformed_invoices = $transformed_invoices['App\\Models\\Invoice']; - if(count($transformed_invoices) == 1 && array_key_exists($column, $transformed_invoices[0])) + if(count($transformed_invoices) == 1 && array_key_exists($column, $transformed_invoices[0])) { return $transformed_invoices[0][$column]; + } - if(count($transformed_invoices) > 1 && array_key_exists($column, $transformed_invoices[0])) + if(count($transformed_invoices) > 1 && array_key_exists($column, $transformed_invoices[0])) { return implode(', ', array_column($transformed_invoices, $column)); + } return ""; @@ -700,8 +725,9 @@ class BaseExport if($transformer instanceof TaskTransformer && ($entity->invoice ?? false)) { $transformed_invoice = $transformer->includeInvoice($entity); - if(!$transformed_invoice) + if(!$transformed_invoice) { return ''; + } $manager = new Manager(); $manager->setSerializer(new ArraySerializer()); @@ -721,7 +747,7 @@ class BaseExport private function resolvePaymentKey($column, $entity, $transformer) { - if($entity instanceof Payment){ + if($entity instanceof Payment) { $transformed_payment = $transformer->transform($entity); @@ -737,8 +763,9 @@ class BaseExport } - if($column == 'amount') + if($column == 'amount') { return $entity->payments()->exists() ? $entity->payments()->withoutTrashed()->sum('paymentables.amount') : ctrans('texts.unpaid'); + } if($column == 'refunded') { return $entity->payments()->exists() ? $entity->payments()->withoutTrashed()->sum('paymentables.refunded') : ''; @@ -753,24 +780,28 @@ class BaseExport $payment = $entity->payments()->withoutTrashed()->first(); - if(!$payment) + if(!$payment) { return ''; + } - if($column == 'method') + if($column == 'method') { return $payment->translatedType(); + } - if($column == 'currency') + if($column == 'currency') { return $payment?->currency?->code ?? ''; + } $payment_transformer = new PaymentTransformer(); $transformed_payment = $payment_transformer->transform($payment); - if($column == 'status'){ + if($column == 'status') { return $payment->stringStatus($transformed_payment['status_id']); } - if(array_key_exists($column, $transformed_payment)) + if(array_key_exists($column, $transformed_payment)) { return $transformed_payment[$column]; + } return ''; @@ -782,8 +813,9 @@ class BaseExport $status_parameters = explode(',', $status); - if(in_array('all', $status_parameters)) + if(in_array('all', $status_parameters)) { return $query; + } $query->where(function ($nested) use ($status_parameters) { @@ -816,9 +848,9 @@ class BaseExport ->orWhere('partial_due_date', '<', Carbon::now()); } - if(in_array('viewed', $status_parameters)){ + if(in_array('viewed', $status_parameters)) { - $nested->whereHas('invitations', function ($q){ + $nested->whereHas('invitations', function ($q) { $q->whereNotNull('viewed_date')->whereNotNull('deleted_at'); }); @@ -884,8 +916,9 @@ class BaseExport $first_month_of_year = $this->company->getSetting('first_month_of_year') ?? 1; $fin_year_start = now()->createFromDate(now()->year, $first_month_of_year, 1); - if(now()->lt($fin_year_start)) + if(now()->lt($fin_year_start)) { $fin_year_start->subYearNoOverflow(); + } $this->start_date = $fin_year_start->format('Y-m-d'); $this->end_date = $fin_year_start->copy()->addYear()->subDay()->format('Y-m-d'); @@ -896,8 +929,9 @@ class BaseExport $fin_year_start = now()->createFromDate(now()->year, $first_month_of_year, 1); $fin_year_start->subYearNoOverflow(); - if(now()->subYear()->lt($fin_year_start)) + if(now()->subYear()->lt($fin_year_start)) { $fin_year_start->subYearNoOverflow(); + } $this->start_date = $fin_year_start->format('Y-m-d'); $this->end_date = $fin_year_start->copy()->addYear()->subDay()->format('Y-m-d'); @@ -914,7 +948,7 @@ class BaseExport } /** - * Returns the merged array of + * Returns the merged array of * the entity with the matching * item report keys * @@ -979,8 +1013,9 @@ class BaseExport $prefix = ctrans('texts.expense')." "; $key = array_search($value, $this->expense_report_keys); - if(!$key && $value == 'expense.category') - $key = 'category'; + if(!$key && $value == 'expense.category') { + $key = 'category'; + } } if(!$key) { @@ -1024,42 +1059,36 @@ class BaseExport $key = str_replace('product.', '', $key); $key = str_replace('task.', '', $key); - if(stripos($value, 'custom_value') !== false) - { + if(stripos($value, 'custom_value') !== false) { $parts = explode(".", $value); - if(count($parts) == 2 && in_array($parts[0], ['credit','quote','invoice','purchase_order','recurring_invoice'])){ + if(count($parts) == 2 && in_array($parts[0], ['credit','quote','invoice','purchase_order','recurring_invoice'])) { $entity = "invoice".substr($parts[1], -1); $prefix = ctrans("texts.".$parts[0]); $fallback = "custom_value".substr($parts[1], -1); $custom_field_label = $helper->makeCustomField($this->company->custom_fields, $entity); - if(strlen($custom_field_label) > 1) + if(strlen($custom_field_label) > 1) { $header[] = $custom_field_label; - else { + } else { $header[] = $prefix . " ". ctrans("texts.{$fallback}"); } - } - elseif(count($parts) == 2 && (stripos($parts[0], 'vendor_contact') !== false || stripos($parts[0], 'contact') !== false)) { + } elseif(count($parts) == 2 && (stripos($parts[0], 'vendor_contact') !== false || stripos($parts[0], 'contact') !== false)) { $parts[0] = str_replace('vendor_contact', 'contact', $parts[0]); $entity = "contact".substr($parts[1], -1); $custom_field_string = strlen($helper->makeCustomField($this->company->custom_fields, $entity)) > 1 ? $helper->makeCustomField($this->company->custom_fields, $entity) : ctrans("texts.{$parts[1]}"); $header[] = ctrans("texts.{$parts[0]}") . " " . $custom_field_string; - } - elseif(count($parts) == 2 && in_array(substr($original_key, 0, -1), ['credit','quote','invoice','purchase_order','recurring_invoice','task'])){ - $custom_field_string = strlen($helper->makeCustomField($this->company->custom_fields, "product".substr($original_key,-1))) > 1 ? $helper->makeCustomField($this->company->custom_fields, "product".substr($original_key,-1)) : ctrans("texts.{$parts[1]}"); + } elseif(count($parts) == 2 && in_array(substr($original_key, 0, -1), ['credit','quote','invoice','purchase_order','recurring_invoice','task'])) { + $custom_field_string = strlen($helper->makeCustomField($this->company->custom_fields, "product".substr($original_key, -1))) > 1 ? $helper->makeCustomField($this->company->custom_fields, "product".substr($original_key, -1)) : ctrans("texts.{$parts[1]}"); $header[] = ctrans("texts.{$parts[0]}") . " " . $custom_field_string; - } - else{ + } else { $header[] = "{$prefix}" . ctrans("texts.{$key}"); } - } - else - { + } else { $header[] = "{$prefix}" . ctrans("texts.{$key}"); } } @@ -1104,7 +1133,7 @@ class BaseExport $value = 'image'; } - if($value == 'tax_id') { + if($value == 'tax_id') { $column_key = 'tax_category'; $value = 'tax_category'; } @@ -1119,7 +1148,7 @@ class BaseExport } return $clean_row; - } + } public function processItemMetaData(array $row, $resource): array { @@ -1146,11 +1175,13 @@ class BaseExport $column_key = $value; - if($value == 'type_id' || $value == 'item.type_id') + if($value == 'type_id' || $value == 'item.type_id') { $column_key = 'type'; + } - if($value == 'tax_id' || $value == 'item.tax_id') + if($value == 'tax_id' || $value == 'item.tax_id') { $column_key = 'tax_category'; + } $clean_row[$key]['entity'] = $report_keys[0]; $clean_row[$key]['id'] = $report_keys[1] ?? $report_keys[0]; @@ -1162,6 +1193,6 @@ class BaseExport } return $clean_row; - } + } } diff --git a/app/Export/CSV/ClientExport.php b/app/Export/CSV/ClientExport.php index 16f9ca154d..29178f5236 100644 --- a/app/Export/CSV/ClientExport.php +++ b/app/Export/CSV/ClientExport.php @@ -11,16 +11,16 @@ namespace App\Export\CSV; +use App\Libraries\MultiDB; +use App\Models\Client; +use App\Models\Company; +use App\Transformers\ClientContactTransformer; +use App\Transformers\ClientTransformer; use App\Utils\Ninja; use App\Utils\Number; -use App\Models\Client; -use League\Csv\Writer; -use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Support\Facades\App; -use App\Transformers\ClientTransformer; use Illuminate\Database\Eloquent\Builder; -use App\Transformers\ClientContactTransformer; +use Illuminate\Support\Facades\App; +use League\Csv\Writer; class ClientExport extends BaseExport { @@ -92,9 +92,9 @@ class ClientExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($client) { @@ -126,7 +126,7 @@ class ClientExport extends BaseExport $query = $this->addDateRange($query); - return $query; + return $query; } @@ -191,10 +191,11 @@ class ClientExport extends BaseExport $clean_row[$key]['value'] = $row[$column_key]; $clean_row[$key]['identifier'] = $value; - if(in_array($clean_row[$key]['id'], ['paid_to_date', 'balance', 'credit_balance','payment_balance'])) + if(in_array($clean_row[$key]['id'], ['paid_to_date', 'balance', 'credit_balance','payment_balance'])) { $clean_row[$key]['display_value'] = Number::formatMoney($row[$column_key], $resource); - else + } else { $clean_row[$key]['display_value'] = $row[$column_key]; + } } diff --git a/app/Export/CSV/ContactExport.php b/app/Export/CSV/ContactExport.php index e07cf64d32..558c693319 100644 --- a/app/Export/CSV/ContactExport.php +++ b/app/Export/CSV/ContactExport.php @@ -88,9 +88,9 @@ class ContactExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($contact) { diff --git a/app/Export/CSV/CreditExport.php b/app/Export/CSV/CreditExport.php index c5c05f3c23..d0a29ea3c7 100644 --- a/app/Export/CSV/CreditExport.php +++ b/app/Export/CSV/CreditExport.php @@ -11,15 +11,15 @@ namespace App\Export\CSV; +use App\Libraries\MultiDB; +use App\Models\Company; +use App\Models\Credit; +use App\Transformers\CreditTransformer; use App\Utils\Ninja; use App\Utils\Number; -use App\Models\Credit; -use League\Csv\Writer; -use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Support\Facades\App; -use App\Transformers\CreditTransformer; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\App; +use League\Csv\Writer; class CreditExport extends BaseExport { @@ -43,9 +43,9 @@ class CreditExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($credit) { @@ -70,10 +70,11 @@ class CreditExport extends BaseExport $clean_row[$key]['value'] = $row[$column_key]; $clean_row[$key]['identifier'] = $value; - if(in_array($clean_row[$key]['id'], ['paid_to_date','total_taxes','amount', 'balance', 'partial', 'refunded', 'applied','unit_cost','cost','price'])) + if(in_array($clean_row[$key]['id'], ['paid_to_date','total_taxes','amount', 'balance', 'partial', 'refunded', 'applied','unit_cost','cost','price'])) { $clean_row[$key]['display_value'] = Number::formatMoney($row[$column_key], $resource->client); - else + } else { $clean_row[$key]['display_value'] = $row[$column_key]; + } } @@ -139,10 +140,9 @@ class CreditExport extends BaseExport $entity[$keyval] = $transformed_credit[$credit_key]; } elseif (isset($transformed_credit[$keyval])) { $entity[$keyval] = $transformed_credit[$keyval]; - } elseif(isset($transformed_credit[$searched_credit_key])){ + } elseif(isset($transformed_credit[$searched_credit_key])) { $entity[$keyval] = $transformed_credit[$searched_credit_key]; - } - else { + } else { $entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer); } diff --git a/app/Export/CSV/DocumentExport.php b/app/Export/CSV/DocumentExport.php index cc4482c063..a5518da707 100644 --- a/app/Export/CSV/DocumentExport.php +++ b/app/Export/CSV/DocumentExport.php @@ -49,9 +49,9 @@ class DocumentExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($document) { diff --git a/app/Export/CSV/ExpenseExport.php b/app/Export/CSV/ExpenseExport.php index 7b51401629..ee8d5bf0c7 100644 --- a/app/Export/CSV/ExpenseExport.php +++ b/app/Export/CSV/ExpenseExport.php @@ -43,9 +43,9 @@ class ExpenseExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($resource) { diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php index 4dc4ee3d8b..4773ec3aa2 100644 --- a/app/Export/CSV/InvoiceExport.php +++ b/app/Export/CSV/InvoiceExport.php @@ -11,16 +11,14 @@ namespace App\Export\CSV; -use App\Utils\Ninja; -use App\Utils\Number; -use League\Csv\Writer; +use App\Libraries\MultiDB; use App\Models\Company; use App\Models\Invoice; -use App\Libraries\MultiDB; -use App\Export\CSV\BaseExport; -use Illuminate\Support\Facades\App; use App\Transformers\InvoiceTransformer; +use App\Utils\Ninja; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\App; +use League\Csv\Writer; class InvoiceExport extends BaseExport { @@ -74,9 +72,9 @@ class InvoiceExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($resource) { diff --git a/app/Export/CSV/InvoiceItemExport.php b/app/Export/CSV/InvoiceItemExport.php index ba2dc00da4..8ccc8a39ff 100644 --- a/app/Export/CSV/InvoiceItemExport.php +++ b/app/Export/CSV/InvoiceItemExport.php @@ -82,9 +82,9 @@ class InvoiceItemExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $query->cursor() @@ -131,7 +131,7 @@ class InvoiceItemExport extends BaseExport $transformed_items = []; foreach ($invoice->line_items as $item) { - $item_array = []; + $item_array = []; foreach (array_values(array_intersect($this->input['report_keys'], $this->item_report_keys)) as $key) { //items iterator produces item array @@ -139,16 +139,17 @@ class InvoiceItemExport extends BaseExport $tmp_key = str_replace("item.", "", $key); - if($tmp_key == 'type_id') + if($tmp_key == 'type_id') { $tmp_key = 'type'; + } - if($tmp_key == 'tax_id') + if($tmp_key == 'tax_id') { $tmp_key = 'tax_category'; + } if (property_exists($item, $tmp_key)) { $item_array[$key] = $item->{$tmp_key}; - } - else { + } else { $item_array[$key] = ''; } } @@ -174,15 +175,15 @@ class InvoiceItemExport extends BaseExport $parts = explode('.', $key); - if(is_array($parts) && $parts[0] == 'item') + if(is_array($parts) && $parts[0] == 'item') { continue; + } if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) { $entity[$key] = $transformed_invoice[$parts[1]]; - }else if (array_key_exists($key, $transformed_invoice)) { + } elseif (array_key_exists($key, $transformed_invoice)) { $entity[$key] = $transformed_invoice[$key]; - } - else { + } else { $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer); } } diff --git a/app/Export/CSV/PaymentExport.php b/app/Export/CSV/PaymentExport.php index 7f77563f9b..48f996fae7 100644 --- a/app/Export/CSV/PaymentExport.php +++ b/app/Export/CSV/PaymentExport.php @@ -71,8 +71,6 @@ class PaymentExport extends BaseExport return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; })->toArray(); - nlog($header); - $report = $query->cursor() ->map(function ($resource) { $row = $this->buildRow($resource); diff --git a/app/Export/CSV/ProductExport.php b/app/Export/CSV/ProductExport.php index d36c31b54e..7963cb76be 100644 --- a/app/Export/CSV/ProductExport.php +++ b/app/Export/CSV/ProductExport.php @@ -41,14 +41,14 @@ class ProductExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($resource) { $row = $this->buildRow($resource); - return $this->processMetaData($row, $resource); + return $this->processMetaData($row, $resource); })->toArray(); return array_merge(['columns' => $header], $report); diff --git a/app/Export/CSV/PurchaseOrderExport.php b/app/Export/CSV/PurchaseOrderExport.php index 45e8a6adb1..5f2ba4fbc1 100644 --- a/app/Export/CSV/PurchaseOrderExport.php +++ b/app/Export/CSV/PurchaseOrderExport.php @@ -11,15 +11,14 @@ namespace App\Export\CSV; -use App\Utils\Ninja; -use App\Utils\Number; -use League\Csv\Writer; -use App\Models\Company; use App\Libraries\MultiDB; +use App\Models\Company; use App\Models\PurchaseOrder; -use Illuminate\Support\Facades\App; use App\Transformers\PurchaseOrderTransformer; +use App\Utils\Ninja; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\App; +use League\Csv\Writer; class PurchaseOrderExport extends BaseExport { @@ -116,9 +115,9 @@ class PurchaseOrderExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($resource) { diff --git a/app/Export/CSV/PurchaseOrderItemExport.php b/app/Export/CSV/PurchaseOrderItemExport.php index 3738ec5b6d..1351be3562 100644 --- a/app/Export/CSV/PurchaseOrderItemExport.php +++ b/app/Export/CSV/PurchaseOrderItemExport.php @@ -11,14 +11,14 @@ namespace App\Export\CSV; -use App\Utils\Ninja; -use League\Csv\Writer; -use App\Models\Company; use App\Libraries\MultiDB; +use App\Models\Company; use App\Models\PurchaseOrder; -use Illuminate\Support\Facades\App; -use Illuminate\Database\Eloquent\Builder; use App\Transformers\PurchaseOrderTransformer; +use App\Utils\Ninja; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\App; +use League\Csv\Writer; class PurchaseOrderItemExport extends BaseExport { @@ -74,21 +74,21 @@ class PurchaseOrderItemExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $query->cursor() ->each(function ($resource) { - $this->iterateItems($resource); + $this->iterateItems($resource); - foreach($this->storage_array as $row) { - $this->storage_item_array[] = $this->processItemMetaData($row, $resource); - } + foreach($this->storage_array as $row) { + $this->storage_item_array[] = $this->processItemMetaData($row, $resource); + } - $this->storage_array = []; + $this->storage_array = []; - }); + }); return array_merge(['columns' => $header], $this->storage_item_array); } diff --git a/app/Export/CSV/QuoteItemExport.php b/app/Export/CSV/QuoteItemExport.php index 0db08629c6..fe8cbb593a 100644 --- a/app/Export/CSV/QuoteItemExport.php +++ b/app/Export/CSV/QuoteItemExport.php @@ -76,23 +76,23 @@ class QuoteItemExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); - $query->cursor() - ->each(function ($resource) { - $this->iterateItems($resource); + $query->cursor() + ->each(function ($resource) { + $this->iterateItems($resource); - foreach($this->storage_array as $row) { - $this->storage_item_array[] = $this->processItemMetaData($row, $resource); - } + foreach($this->storage_array as $row) { + $this->storage_item_array[] = $this->processItemMetaData($row, $resource); + } - $this->storage_array = []; + $this->storage_array = []; - }); + }); - return array_merge(['columns' => $header], $this->storage_item_array); + return array_merge(['columns' => $header], $this->storage_item_array); } @@ -103,7 +103,7 @@ class QuoteItemExport extends BaseExport //load the CSV document from a string $this->csv = Writer::createFromString(); - $query = $this->init(); + $query = $this->init(); //insert the header $this->csv->insertOne($this->buildHeader()); @@ -127,7 +127,7 @@ class QuoteItemExport extends BaseExport $transformed_items = []; foreach ($quote->line_items as $item) { - $item_array = []; + $item_array = []; foreach (array_values(array_intersect($this->input['report_keys'], $this->item_report_keys)) as $key) { //items iterator produces item array @@ -135,16 +135,17 @@ class QuoteItemExport extends BaseExport $tmp_key = str_replace("item.", "", $key); - if($tmp_key == 'type_id') + if($tmp_key == 'type_id') { $tmp_key = 'type'; + } - if($tmp_key == 'tax_id') + if($tmp_key == 'tax_id') { $tmp_key = 'tax_category'; + } if (property_exists($item, $tmp_key)) { $item_array[$key] = $item->{$tmp_key}; - } - else { + } else { $item_array[$key] = ''; } } diff --git a/app/Export/CSV/RecurringInvoiceExport.php b/app/Export/CSV/RecurringInvoiceExport.php index 3234b06743..b88601ba99 100644 --- a/app/Export/CSV/RecurringInvoiceExport.php +++ b/app/Export/CSV/RecurringInvoiceExport.php @@ -88,9 +88,9 @@ class RecurringInvoiceExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($resource) { diff --git a/app/Export/CSV/TaskExport.php b/app/Export/CSV/TaskExport.php index b2eb6425c5..7d8271d860 100644 --- a/app/Export/CSV/TaskExport.php +++ b/app/Export/CSV/TaskExport.php @@ -101,17 +101,16 @@ class TaskExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $query->cursor() ->each(function ($resource) { $this->buildRow($resource); - foreach($this->storage_array as $row) - { + foreach($this->storage_array as $row) { $this->storage_item_array[] = $this->processMetaData($row, $resource); } diff --git a/app/Export/CSV/VendorExport.php b/app/Export/CSV/VendorExport.php index 062c09187d..259f53c59c 100644 --- a/app/Export/CSV/VendorExport.php +++ b/app/Export/CSV/VendorExport.php @@ -12,8 +12,8 @@ namespace App\Export\CSV; use App\Libraries\MultiDB; -use App\Models\Vendor; use App\Models\Company; +use App\Models\Vendor; use App\Transformers\VendorContactTransformer; use App\Transformers\VendorTransformer; use App\Utils\Ninja; @@ -73,9 +73,9 @@ class VendorExport extends BaseExport $headerdisplay = $this->buildHeader(); - $header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){ - return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; - })->toArray(); + $header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) { + return ['identifier' => $key, 'display_value' => $headerdisplay[$value]]; + })->toArray(); $report = $query->cursor() ->map(function ($resource) { diff --git a/app/Factory/CompanyFactory.php b/app/Factory/CompanyFactory.php index 52324d698a..b48904b6d3 100644 --- a/app/Factory/CompanyFactory.php +++ b/app/Factory/CompanyFactory.php @@ -11,13 +11,13 @@ namespace App\Factory; -use App\Utils\Ninja; -use App\Models\Company; -use App\Libraries\MultiDB; -use App\Utils\Traits\MakesHash; -use App\DataMapper\Tax\TaxModel; -use App\DataMapper\CompanySettings; use App\DataMapper\ClientRegistrationFields; +use App\DataMapper\CompanySettings; +use App\DataMapper\Tax\TaxModel; +use App\Libraries\MultiDB; +use App\Models\Company; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; class CompanyFactory { diff --git a/app/Factory/DesignFactory.php b/app/Factory/DesignFactory.php index 0013e37d7b..b8b8fe2092 100644 --- a/app/Factory/DesignFactory.php +++ b/app/Factory/DesignFactory.php @@ -25,6 +25,8 @@ class DesignFactory $design->is_active = true; $design->is_custom = true; $design->name = ''; + $design->is_template = false; + $design->entities = ''; $design->design = new DesignBlocks(); return $design; diff --git a/app/Factory/InvoiceItemFactory.php b/app/Factory/InvoiceItemFactory.php index 08c13f4784..f81872dc8c 100644 --- a/app/Factory/InvoiceItemFactory.php +++ b/app/Factory/InvoiceItemFactory.php @@ -63,7 +63,7 @@ class InvoiceItemFactory $item->line_total = $item->quantity * $item->cost; $item->is_amount_discount = true; $item->discount = $faker->numberBetween(1, 10); - $item->notes = $faker->realText(50); + $item->notes = str_replace(['"',"'"], ['',""], $faker->realText(20)); $item->product_key = $faker->word(); // $item->custom_value1 = $faker->realText(10); // $item->custom_value2 = $faker->realText(10); diff --git a/app/Factory/RecurringExpenseToExpenseFactory.php b/app/Factory/RecurringExpenseToExpenseFactory.php index 921130ac91..4d6bff4c4c 100644 --- a/app/Factory/RecurringExpenseToExpenseFactory.php +++ b/app/Factory/RecurringExpenseToExpenseFactory.php @@ -248,10 +248,10 @@ class RecurringExpenseToExpenseFactory $final_date = now()->addMonths($output-now()->month); $output = \sprintf( - '%s %s', - $final_date->translatedFormat('F'), - $final_date->year, - ); + '%s %s', + $final_date->translatedFormat('F'), + $final_date->year, + ); } $value = preg_replace( diff --git a/app/Factory/UserFactory.php b/app/Factory/UserFactory.php index 9b15037f62..c8fbc4f4d3 100644 --- a/app/Factory/UserFactory.php +++ b/app/Factory/UserFactory.php @@ -27,7 +27,7 @@ class UserFactory $user->last_login = now(); $user->failed_logins = 0; $user->signature = ''; - $user->theme_id = 0; + $user->theme_id = 0; $user->user_logged_in_notification = true; return $user; diff --git a/app/Filters/BankTransactionFilters.php b/app/Filters/BankTransactionFilters.php index 15c02a7b97..11d27df790 100644 --- a/app/Filters/BankTransactionFilters.php +++ b/app/Filters/BankTransactionFilters.php @@ -53,19 +53,19 @@ class BankTransactionFilters extends QueryFilters } -/** - * Filter based on client status. - * - * Statuses we need to handle - * - all - * - unmatched - * - matched - * - converted - * - deposits - * - withdrawals - * - * @return Builder - */ + /** + * Filter based on client status. + * + * Statuses we need to handle + * - all + * - unmatched + * - matched + * - converted + * - deposits + * - withdrawals + * + * @return Builder + */ public function client_status(string $value = ''): Builder { if (strlen($value) == 0) { diff --git a/app/Filters/CreditFilters.php b/app/Filters/CreditFilters.php index bd17e34819..a69daa60dd 100644 --- a/app/Filters/CreditFilters.php +++ b/app/Filters/CreditFilters.php @@ -144,7 +144,7 @@ class CreditFilters extends QueryFilters return $this->builder->company(); } -// return $this->builder->whereCompanyId(auth()->user()->company()->id); + // return $this->builder->whereCompanyId(auth()->user()->company()->id); } /** diff --git a/app/Filters/DesignFilters.php b/app/Filters/DesignFilters.php index 88593f2198..bd489b05c4 100644 --- a/app/Filters/DesignFilters.php +++ b/app/Filters/DesignFilters.php @@ -54,6 +54,19 @@ class DesignFilters extends QueryFilters return $this->builder->orderBy($sort_col[0], $sort_col[1]); } + public function entities(string $entities = ''): Builder + { + + if (strlen($entities) == 0 || str_contains($entities, ',')) { + return $this->builder; + } + + return $this->builder + ->where('is_template', true) + ->whereRaw('FIND_IN_SET( ? ,entities)', [trim($entities)]); + + } + /** * Filters the query by the users company ID. * @@ -64,11 +77,22 @@ class DesignFilters extends QueryFilters /** @var \App\Models\User $user */ $user = auth()->user(); - return $this->builder->where(function ($query) use($user){ + return $this->builder->where(function ($query) use ($user) { $query->where('company_id', $user->company()->id)->orWhere('company_id', null)->orderBy('id', 'asc'); }); } + public function template(string $template = 'false'): Builder + { + + if (strlen($template) == 0) { + return $this->builder; + } + + $bool_val = $template == 'true' ? true : false; + + return $this->builder->where('is_template', $bool_val); + } /** * Filter the designs by `is_custom` column. * diff --git a/app/Filters/ExpenseFilters.php b/app/Filters/ExpenseFilters.php index a2ddc98e3c..264be55d03 100644 --- a/app/Filters/ExpenseFilters.php +++ b/app/Filters/ExpenseFilters.php @@ -40,8 +40,8 @@ class ExpenseFilters extends QueryFilters ->orWhere('custom_value3', 'like', '%'.$filter.'%') ->orWhere('custom_value4', 'like', '%'.$filter.'%') ->orWhereHas('category', function ($q) use ($filter) { - $q->where('name', 'like', '%'.$filter.'%'); - }); + $q->where('name', 'like', '%'.$filter.'%'); + }); }); } @@ -125,9 +125,9 @@ class ExpenseFilters extends QueryFilters $search_key = $split[0] == 'client' ? 'client_id' : 'project_id'; - return $this->builder->whereHas('invoice', function ($query) use ($search_key, $split){ - $query->where($search_key, $this->decodePrimaryKey($split[1])) - ->whereIn('status_id', [\App\Models\Invoice::STATUS_DRAFT, \App\Models\Invoice::STATUS_SENT, \App\Models\Invoice::STATUS_PARTIAL]); + return $this->builder->whereHas('invoice', function ($query) use ($search_key, $split) { + $query->where($search_key, $this->decodePrimaryKey($split[1])) + ->whereIn('status_id', [\App\Models\Invoice::STATUS_DRAFT, \App\Models\Invoice::STATUS_SENT, \App\Models\Invoice::STATUS_PARTIAL]); }); } diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 91e426192f..58af558b99 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -11,14 +11,13 @@ namespace App\Filters; -use RuntimeException; use App\Models\Client; use App\Models\Invoice; -use App\Filters\QueryFilters; -use InvalidArgumentException; -use Illuminate\Support\Carbon; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Carbon; +use InvalidArgumentException; +use RuntimeException; /** * InvoiceFilters. @@ -241,15 +240,13 @@ class InvoiceFilters extends QueryFilters return $this->builder; } - try{ + try { $start_date = Carbon::parse($parts[1]); $end_date = Carbon::parse($parts[2]); return $this->builder->whereBetween($parts[0], [$start_date, $end_date]); - } - - catch(\Exception $e){ + } catch(\Exception $e) { return $this->builder; } diff --git a/app/Filters/PaymentFilters.php b/app/Filters/PaymentFilters.php index bc16744d4b..dbdb839bde 100644 --- a/app/Filters/PaymentFilters.php +++ b/app/Filters/PaymentFilters.php @@ -12,9 +12,8 @@ namespace App\Filters; use App\Models\Payment; -use Illuminate\Support\Carbon; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder; +use Illuminate\Support\Carbon; /** * PaymentFilters. @@ -37,39 +36,39 @@ class PaymentFilters extends QueryFilters return $this->builder->where(function ($query) use ($filter) { $query->where('amount', 'like', '%'.$filter.'%') ->orWhere('date', 'like', '%'.$filter.'%') - ->orWhere('number','like', '%'.$filter.'%') + ->orWhere('number', 'like', '%'.$filter.'%') ->orWhere('transaction_reference', 'like', '%'.$filter.'%') ->orWhere('custom_value1', 'like', '%'.$filter.'%') ->orWhere('custom_value2', 'like', '%'.$filter.'%') ->orWhere('custom_value3', 'like', '%'.$filter.'%') ->orWhere('custom_value4', 'like', '%'.$filter.'%') ->orWhereHas('client', function ($q) use ($filter) { - $q->where('name', 'like', '%'.$filter.'%'); - }) + $q->where('name', 'like', '%'.$filter.'%'); + }) ->orWhereHas('client.contacts', function ($q) use ($filter) { - $q->where('first_name', 'like', '%'.$filter.'%') - ->orWhere('last_name', 'like', '%'.$filter.'%') - ->orWhere('email', 'like', '%'.$filter.'%'); - }); + $q->where('first_name', 'like', '%'.$filter.'%') + ->orWhere('last_name', 'like', '%'.$filter.'%') + ->orWhere('email', 'like', '%'.$filter.'%'); + }); }); } - /** - * Filter based on client status. - * - * Statuses we need to handle - * - all - * - pending - * - cancelled - * - failed - * - completed - * - partially refunded - * - refunded - * - * @param string $value The payment status as seen by the client - * @return Builder - */ + /** + * Filter based on client status. + * + * Statuses we need to handle + * - all + * - pending + * - cancelled + * - failed + * - completed + * - partially refunded + * - refunded + * + * @param string $value The payment status as seen by the client + * @return Builder + */ public function client_status(string $value = ''): Builder { if (strlen($value) == 0) { @@ -190,15 +189,13 @@ class PaymentFilters extends QueryFilters return $this->builder; } - try{ + try { $start_date = Carbon::parse($parts[1]); $end_date = Carbon::parse($parts[2]); return $this->builder->whereBetween($parts[0], [$start_date, $end_date]); - } - - catch(\Exception $e){ + } catch(\Exception $e) { return $this->builder; } diff --git a/app/Filters/PurchaseOrderFilters.php b/app/Filters/PurchaseOrderFilters.php index 8948a619f4..0d5c124498 100644 --- a/app/Filters/PurchaseOrderFilters.php +++ b/app/Filters/PurchaseOrderFilters.php @@ -145,7 +145,7 @@ class PurchaseOrderFilters extends QueryFilters return $this->builder->company(); } -// return $this->builder->whereCompanyId(auth()->user()->company()->id); + // return $this->builder->whereCompanyId(auth()->user()->company()->id); } /** diff --git a/app/Filters/QuoteFilters.php b/app/Filters/QuoteFilters.php index 220960a219..c28d0450cb 100644 --- a/app/Filters/QuoteFilters.php +++ b/app/Filters/QuoteFilters.php @@ -42,10 +42,10 @@ class QuoteFilters extends QueryFilters $q->where('name', 'like', '%'.$filter.'%'); }) ->orWhereHas('client.contacts', function ($q) use ($filter) { - $q->where('first_name', 'like', '%'.$filter.'%') - ->orWhere('last_name', 'like', '%'.$filter.'%') - ->orWhere('email', 'like', '%'.$filter.'%'); - }); + $q->where('first_name', 'like', '%'.$filter.'%') + ->orWhere('last_name', 'like', '%'.$filter.'%') + ->orWhere('email', 'like', '%'.$filter.'%'); + }); }); } @@ -146,7 +146,7 @@ class QuoteFilters extends QueryFilters return $this->builder; } - if($sort_col[0] == 'client_id'){ + if($sort_col[0] == 'client_id') { return $this->builder->orderBy(\App\Models\Client::select('name') ->whereColumn('clients.id', 'quotes.client_id'), $sort_col[1]); diff --git a/app/Filters/RecurringInvoiceFilters.php b/app/Filters/RecurringInvoiceFilters.php index 71fcca9d10..81060eed61 100644 --- a/app/Filters/RecurringInvoiceFilters.php +++ b/app/Filters/RecurringInvoiceFilters.php @@ -34,20 +34,20 @@ class RecurringInvoiceFilters extends QueryFilters } return $this->builder->where(function ($query) use ($filter) { - $query->where('date', 'like', '%'.$filter.'%') - ->orWhere('amount', 'like', '%'.$filter.'%') - ->orWhere('custom_value1', 'like', '%'.$filter.'%') - ->orWhere('custom_value2', 'like', '%'.$filter.'%') - ->orWhere('custom_value3', 'like', '%'.$filter.'%') - ->orWhere('custom_value4', 'like', '%'.$filter.'%') - ->orWhereHas('client', function ($q) use ($filter) { - $q->where('name', 'like', '%'.$filter.'%'); - }) - ->orWhereHas('client.contacts', function ($q) use ($filter) { - $q->where('first_name', 'like', '%'.$filter.'%') - ->orWhere('last_name', 'like', '%'.$filter.'%') - ->orWhere('email', 'like', '%'.$filter.'%'); - }); + $query->where('date', 'like', '%'.$filter.'%') + ->orWhere('amount', 'like', '%'.$filter.'%') + ->orWhere('custom_value1', 'like', '%'.$filter.'%') + ->orWhere('custom_value2', 'like', '%'.$filter.'%') + ->orWhere('custom_value3', 'like', '%'.$filter.'%') + ->orWhere('custom_value4', 'like', '%'.$filter.'%') + ->orWhereHas('client', function ($q) use ($filter) { + $q->where('name', 'like', '%'.$filter.'%'); + }) + ->orWhereHas('client.contacts', function ($q) use ($filter) { + $q->where('first_name', 'like', '%'.$filter.'%') + ->orWhere('last_name', 'like', '%'.$filter.'%') + ->orWhere('email', 'like', '%'.$filter.'%'); + }); }); } diff --git a/app/Filters/TaskFilters.php b/app/Filters/TaskFilters.php index 481fb44299..eb3ca35c41 100644 --- a/app/Filters/TaskFilters.php +++ b/app/Filters/TaskFilters.php @@ -41,16 +41,16 @@ class TaskFilters extends QueryFilters ->orWhere('custom_value3', 'like', '%'.$filter.'%') ->orWhere('custom_value4', 'like', '%'.$filter.'%') ->orWhereHas('project', function ($q) use ($filter) { - $q->where('name', 'like', '%'.$filter.'%'); - }) + $q->where('name', 'like', '%'.$filter.'%'); + }) ->orWhereHas('client', function ($q) use ($filter) { - $q->where('name', 'like', '%'.$filter.'%'); - }) + $q->where('name', 'like', '%'.$filter.'%'); + }) ->orWhereHas('client.contacts', function ($q) use ($filter) { - $q->where('first_name', 'like', '%'.$filter.'%') - ->orWhere('last_name', 'like', '%'.$filter.'%') - ->orWhere('email', 'like', '%'.$filter.'%'); - }); + $q->where('first_name', 'like', '%'.$filter.'%') + ->orWhere('last_name', 'like', '%'.$filter.'%') + ->orWhere('email', 'like', '%'.$filter.'%'); + }); }); } @@ -136,7 +136,7 @@ class TaskFilters extends QueryFilters $status_parameters = explode(',', $value); - if(count($status_parameters) >= 1){ + if(count($status_parameters) >= 1) { $this->builder->where(function ($query) use ($status_parameters) { $query->whereIn('status_id', $this->transformKeys($status_parameters))->whereNull('invoice_id'); diff --git a/app/Helpers/Bank/Yodlee/DTO/AccountSummary.php b/app/Helpers/Bank/Yodlee/DTO/AccountSummary.php index 346496411f..d7357c9fe3 100644 --- a/app/Helpers/Bank/Yodlee/DTO/AccountSummary.php +++ b/app/Helpers/Bank/Yodlee/DTO/AccountSummary.php @@ -11,10 +11,9 @@ namespace App\Helpers\Bank\Yodlee\DTO; -use Spatie\LaravelData\Data; -use Spatie\LaravelData\Attributes\MapInputName; -use Spatie\LaravelData\Attributes\MapOutputName; use Illuminate\Support\Collection; +use Spatie\LaravelData\Attributes\MapInputName; +use Spatie\LaravelData\Data; /** * [ @@ -72,40 +71,40 @@ use Illuminate\Support\Collection; */ class AccountSummary extends Data { - public ?int $id; + public ?int $id; - #[MapInputName('CONTAINER')] - public ?string $account_type = ''; + #[MapInputName('CONTAINER')] + public ?string $account_type = ''; - #[MapInputName('accountName')] - public ?string $account_name = ''; + #[MapInputName('accountName')] + public ?string $account_name = ''; - #[MapInputName('accountStatus')] - public ?string $account_status = ''; + #[MapInputName('accountStatus')] + public ?string $account_status = ''; - #[MapInputName('accountNumber')] - public ?string $account_number = ''; + #[MapInputName('accountNumber')] + public ?string $account_number = ''; - #[MapInputName('providerAccountId')] - public int $provider_account_id; + #[MapInputName('providerAccountId')] + public int $provider_account_id; - #[MapInputName('providerId')] - public ?string $provider_id = ''; + #[MapInputName('providerId')] + public ?string $provider_id = ''; - #[MapInputName('providerName')] - public ?string $provider_name = ''; + #[MapInputName('providerName')] + public ?string $provider_name = ''; - public ?string $nickname = ''; + public ?string $nickname = ''; - public ?float $current_balance = 0; - public ?string $account_currency = ''; + public ?float $current_balance = 0; + public ?string $account_currency = ''; - public static function prepareForPipeline(Collection $properties) : Collection - { + public static function prepareForPipeline(Collection $properties) : Collection + { - $properties->put('current_balance', $properties['currentBalance']['amount'] ?? 0); - $properties->put('account_currency', $properties['currentBalance']['currency'] ?? 0); + $properties->put('current_balance', $properties['currentBalance']['amount'] ?? 0); + $properties->put('account_currency', $properties['currentBalance']['currency'] ?? 0); - return $properties; - } -} \ No newline at end of file + return $properties; + } +} diff --git a/app/Helpers/Bank/Yodlee/Transformer/AccountTransformer.php b/app/Helpers/Bank/Yodlee/Transformer/AccountTransformer.php index ceb1417c75..9c44c3784b 100644 --- a/app/Helpers/Bank/Yodlee/Transformer/AccountTransformer.php +++ b/app/Helpers/Bank/Yodlee/Transformer/AccountTransformer.php @@ -88,20 +88,19 @@ class AccountTransformer implements AccountTransformerInterface if(property_exists($account, 'currentBalance')) { $current_balance = $account->currentBalance->amount ?? 0; $account_currency = $account->currentBalance->currency ?? ''; - } - elseif(property_exists($account, 'balance')){ + } elseif(property_exists($account, 'balance')) { $current_balance = $account->balance->amount ?? 0; $account_currency = $account->balance->currency ?? ''; } $account_status = $account->accountStatus; - if(property_exists($account, 'dataset')){ + if(property_exists($account, 'dataset')) { $dataset = $account->dataset[0]; $status = false; $update = false; - match($dataset->additionalStatus ?? ''){ + match($dataset->additionalStatus ?? '') { 'LOGIN_IN_PROGRESS' => $status = 'Data retrieval in progress.', 'USER_INPUT_REQUIRED' => $status = 'Please reconnect your account, authentication required.', 'LOGIN_SUCCESS' => $status = 'Data retrieval in progress', @@ -113,24 +112,23 @@ class AccountTransformer implements AccountTransformerInterface 'PARTIAL_DATA_RETRIEVED' => $status = 'Partial data update failed.', 'PARTIAL_DATA_RETRIEVED_REM_SCHED' => $status = 'Partial data update failed.', 'SUCCESS' => $status = 'All accounts added or updated successfully.', - default => $status = false + default => $status = false }; - if($status){ + if($status) { $account_status = $status; } - match($dataset->updateEligibility ?? ''){ + match($dataset->updateEligibility ?? '') { 'ALLOW_UPDATE' => $update = 'Account connection stable.', 'ALLOW_UPDATE_WITH_CREDENTIALS' => $update = 'Please reconnect your account with updated credentials.', 'DISALLOW_UPDATE' => $update = 'Update not available due to technical issues.', default => $update = false, }; - if($status && $update){ + if($status && $update) { $account_status = $status . ' - ' . $update; - } - elseif($update){ + } elseif($update) { $account_status = $update; } diff --git a/app/Helpers/Bank/Yodlee/Transformer/IncomeTransformer.php b/app/Helpers/Bank/Yodlee/Transformer/IncomeTransformer.php index 48966aa203..73f9e7fe31 100644 --- a/app/Helpers/Bank/Yodlee/Transformer/IncomeTransformer.php +++ b/app/Helpers/Bank/Yodlee/Transformer/IncomeTransformer.php @@ -127,12 +127,14 @@ class IncomeTransformer implements BankRevenueInterface foreach ($transaction->transaction as $transaction) { //do not store duplicate / pending transactions - if (property_exists($transaction, 'status') && $transaction->status == 'PENDING') + if (property_exists($transaction, 'status') && $transaction->status == 'PENDING') { continue; + } //some object do no store amounts ignore these - if(!property_exists($transaction, 'amount')) + if(!property_exists($transaction, 'amount')) { continue; + } $data[] = $this->transformTransaction($transaction); } diff --git a/app/Helpers/Bank/Yodlee/Yodlee.php b/app/Helpers/Bank/Yodlee/Yodlee.php index f8294becd9..6b15e1b2d5 100644 --- a/app/Helpers/Bank/Yodlee/Yodlee.php +++ b/app/Helpers/Bank/Yodlee/Yodlee.php @@ -300,7 +300,7 @@ class Yodlee /** * updateEligibility - * + * * ALLOW_UPDATE * ALLOW_UPDATE_WITH_CREDENTIALS * DISALLOW_UPDATE @@ -308,7 +308,7 @@ class Yodlee /** * additionalStatus - * + * * LOGIN_IN_PROGRESS * DATA_RETRIEVAL_IN_PROGRESS * ACCT_SUMMARY_RECEIVED @@ -339,7 +339,7 @@ class Yodlee * CONSENT_REVOKED * INCORRECT_OAUTH_TOKEN * MIGRATION_IN_PROGRESS - */ + */ /** * IN_PROGRESS LOGIN_IN_PROGRESS Provider login is in progress. @@ -356,12 +356,12 @@ class Yodlee * SUCCESS All accounts under the provider was added or updated successfully. */ - /** - * updateEligibility - * - * ALLOW_UPDATE The status indicates that the account is eligible for the next update and applies to both MFA and non-MFA accounts. For MFA-based accounts, the user may have to provide the MFA details during account refresh. - * ALLOW_UPDATE_WITH_CREDENTIALS The status indicates updating or refreshing the account by directing the user to edit the provided credentials. - * DISALLOW_UPDATE The status indicates the account is not eligible for the update or refresh process due to a site issue or a technical error. - */ + /** + * updateEligibility + * + * ALLOW_UPDATE The status indicates that the account is eligible for the next update and applies to both MFA and non-MFA accounts. For MFA-based accounts, the user may have to provide the MFA details during account refresh. + * ALLOW_UPDATE_WITH_CREDENTIALS The status indicates updating or refreshing the account by directing the user to edit the provided credentials. + * DISALLOW_UPDATE The status indicates the account is not eligible for the update or refresh process due to a site issue or a technical error. + */ } diff --git a/app/Helpers/Epc/EpcQrGenerator.php b/app/Helpers/Epc/EpcQrGenerator.php index 965e2dad1f..a8f4f1518e 100644 --- a/app/Helpers/Epc/EpcQrGenerator.php +++ b/app/Helpers/Epc/EpcQrGenerator.php @@ -64,7 +64,7 @@ class EpcQrGenerator } catch(\Exception $e) { nlog("EPC QR failure => ".$e->getMessage()); return ''; - } catch( InvalidArgumentException $e) { + } catch(InvalidArgumentException $e) { nlog("EPC QR failure => ".$e->getMessage()); return ''; } diff --git a/app/Helpers/Invoice/InvoiceItemSum.php b/app/Helpers/Invoice/InvoiceItemSum.php index b1f7fa9e64..c7d444b9c5 100644 --- a/app/Helpers/Invoice/InvoiceItemSum.php +++ b/app/Helpers/Invoice/InvoiceItemSum.php @@ -11,16 +11,16 @@ namespace App\Helpers\Invoice; -use App\Models\Quote; +use App\DataMapper\BaseSettings; +use App\DataMapper\InvoiceItem; +use App\DataMapper\Tax\RuleInterface; use App\Models\Client; use App\Models\Credit; use App\Models\Invoice; use App\Models\PurchaseOrder; -use App\Models\RecurringQuote; -use App\DataMapper\InvoiceItem; -use App\DataMapper\BaseSettings; +use App\Models\Quote; use App\Models\RecurringInvoice; -use App\DataMapper\Tax\RuleInterface; +use App\Models\RecurringQuote; use App\Utils\Traits\NumberFormatter; class InvoiceItemSum @@ -125,7 +125,7 @@ class InvoiceItemSum private RuleInterface $rule; - public function __construct( RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice) + public function __construct(RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice) { $this->tax_collection = collect([]); @@ -175,14 +175,15 @@ class InvoiceItemSum return $this; } - if (in_array($this->client->company->country()->iso_3166_2, $this->tax_jurisdictions) ) { //only calculate for supported tax jurisdictions + if (in_array($this->client->company->country()->iso_3166_2, $this->tax_jurisdictions)) { //only calculate for supported tax jurisdictions $class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule"; $this->rule = new $class(); - if($this->rule->regionWithNoTaxCoverage($this->client->country->iso_3166_2)) - return $this; + if($this->rule->regionWithNoTaxCoverage($this->client->country->iso_3166_2)) { + return $this; + } $this->rule ->setEntity($this->invoice) @@ -399,7 +400,7 @@ class InvoiceItemSum $item_tax = 0; //$amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount / $this->sub_total)); - $amount = ($this->sub_total > 0) ? $this->item->line_total - ($this->invoice->discount * ( $this->item->line_total / $this->sub_total)) : 0; + $amount = ($this->sub_total > 0) ? $this->item->line_total - ($this->invoice->discount * ($this->item->line_total / $this->sub_total)) : 0; $item_tax_rate1_total = $this->calcAmountLineTax($this->item->tax_rate1, $amount); diff --git a/app/Helpers/Invoice/InvoiceItemSumInclusive.php b/app/Helpers/Invoice/InvoiceItemSumInclusive.php index 7198abbfe8..7ca6fb5e27 100644 --- a/app/Helpers/Invoice/InvoiceItemSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceItemSumInclusive.php @@ -11,14 +11,14 @@ namespace App\Helpers\Invoice; -use App\Models\Quote; +use App\DataMapper\Tax\RuleInterface; use App\Models\Client; use App\Models\Credit; use App\Models\Invoice; use App\Models\PurchaseOrder; -use App\Models\RecurringQuote; +use App\Models\Quote; use App\Models\RecurringInvoice; -use App\DataMapper\Tax\RuleInterface; +use App\Models\RecurringQuote; use App\Utils\Traits\NumberFormatter; class InvoiceItemSumInclusive @@ -404,14 +404,15 @@ class InvoiceItemSumInclusive return $this; } - if (in_array($this->client->company->country()->iso_3166_2, $this->tax_jurisdictions) ) { //only calculate for supported tax jurisdictions + if (in_array($this->client->company->country()->iso_3166_2, $this->tax_jurisdictions)) { //only calculate for supported tax jurisdictions $class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule"; $this->rule = new $class(); - if($this->rule->regionWithNoTaxCoverage($this->client->country->iso_3166_2)) - return $this; + if($this->rule->regionWithNoTaxCoverage($this->client->country->iso_3166_2)) { + return $this; + } $this->rule ->setEntity($this->invoice) diff --git a/app/Helpers/Invoice/InvoiceSum.php b/app/Helpers/Invoice/InvoiceSum.php index 3f32ed486f..3767de76c4 100644 --- a/app/Helpers/Invoice/InvoiceSum.php +++ b/app/Helpers/Invoice/InvoiceSum.php @@ -11,15 +11,15 @@ namespace App\Helpers\Invoice; -use App\Models\Quote; -use App\Utils\Number; use App\Models\Credit; use App\Models\Invoice; use App\Models\PurchaseOrder; -use App\Models\RecurringQuote; +use App\Models\Quote; use App\Models\RecurringInvoice; -use Illuminate\Support\Collection; +use App\Models\RecurringQuote; +use App\Utils\Number; use App\Utils\Traits\NumberFormatter; +use Illuminate\Support\Collection; class InvoiceSum { diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index 69410f54db..3043607fdf 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -11,15 +11,14 @@ namespace App\Helpers\Invoice; -use App\Models\Quote; use App\Models\Credit; use App\Models\Invoice; use App\Models\PurchaseOrder; -use App\Models\RecurringQuote; +use App\Models\Quote; use App\Models\RecurringInvoice; -use Illuminate\Support\Collection; +use App\Models\RecurringQuote; use App\Utils\Traits\NumberFormatter; -use App\Helpers\Invoice\InvoiceItemSumInclusive; +use Illuminate\Support\Collection; class InvoiceSumInclusive { diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index d8c1ad7730..fa02a550be 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -57,7 +57,7 @@ class SwissQrGenerator // - with specified amount // - with human-readable additional information // - using your QR-IBAN - // + // // Likely the most common use-case in the business world. // Create a new instance of QrBill, containing default headers with fixed values @@ -83,7 +83,7 @@ class SwissQrGenerator // Add debtor information // Who has to pay the invoice? This part is optional. - // + // // Notice how you can use two different styles of addresses: CombinedAddress or StructuredAddress // They are interchangeable for creditor as well as debtor. $qrBill->setUltimateDebtor( @@ -121,7 +121,7 @@ class SwissQrGenerator $array = str_split($tempInvoiceNumber); foreach ($array as $char) { if (is_numeric($char)) { - // + // } else { if ($char) { $char = strtolower($char); diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 591041c31c..52a2d85329 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -11,17 +11,17 @@ namespace App\Http\Controllers; -use App\Models\Account; -use App\Libraries\MultiDB; -use App\Utils\TruthSource; -use App\Models\CompanyUser; -use Illuminate\Http\Response; -use App\Jobs\Account\CreateAccount; -use App\Transformers\AccountTransformer; -use App\Transformers\CompanyUserTransformer; -use Illuminate\Foundation\Bus\DispatchesJobs; use App\Http\Requests\Account\CreateAccountRequest; use App\Http\Requests\Account\UpdateAccountRequest; +use App\Jobs\Account\CreateAccount; +use App\Libraries\MultiDB; +use App\Models\Account; +use App\Models\CompanyUser; +use App\Transformers\AccountTransformer; +use App\Transformers\CompanyUserTransformer; +use App\Utils\TruthSource; +use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Http\Response; class AccountController extends BaseController { diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index 2b377c7f5e..5e7e6068d6 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -11,19 +11,19 @@ namespace App\Http\Controllers; -use stdClass; -use App\Utils\Ninja; -use App\Models\Activity; -use Illuminate\Http\Request; -use App\Utils\Traits\MakesHash; -use App\Utils\PhantomJS\Phantom; -use App\Utils\HostedPDF\NinjaPdf; -use App\Utils\Traits\Pdf\PdfMaker; -use App\Utils\Traits\Pdf\PageNumbering; -use Illuminate\Support\Facades\Storage; -use App\Transformers\ActivityTransformer; -use App\Http\Requests\Activity\ShowActivityRequest; use App\Http\Requests\Activity\DownloadHistoricalEntityRequest; +use App\Http\Requests\Activity\ShowActivityRequest; +use App\Models\Activity; +use App\Transformers\ActivityTransformer; +use App\Utils\HostedPDF\NinjaPdf; +use App\Utils\Ninja; +use App\Utils\PhantomJS\Phantom; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\Pdf\PageNumbering; +use App\Utils\Traits\Pdf\PdfMaker; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; +use stdClass; class ActivityController extends BaseController { diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 4d2ad56329..afd98dcafb 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Auth; +use App\Http\Controllers\Controller; +use App\Libraries\MultiDB; use App\Models\Account; use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Http\Request; -use App\Http\Controllers\Controller; -use Illuminate\Support\Facades\Password; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Password; class ForgotPasswordController extends Controller { @@ -90,7 +90,7 @@ class ForgotPasswordController extends Controller $account = Account::find($account_id); } - $is_react = request()->has('react') ? true : false; + $is_react = request()->has('react') ? true : false; return $this->render('auth.passwords.request', ['root' => 'themes', 'account' => $account, 'is_react' => $is_react]); } diff --git a/app/Http/Controllers/Auth/PasswordTimeoutController.php b/app/Http/Controllers/Auth/PasswordTimeoutController.php index 4ce83fa46b..614a48487e 100644 --- a/app/Http/Controllers/Auth/PasswordTimeoutController.php +++ b/app/Http/Controllers/Auth/PasswordTimeoutController.php @@ -25,4 +25,3 @@ class PasswordTimeoutController extends Controller return $cached ? response()->json(['message' => 'Password is valid'], 200) : response()->json(['message' => 'Invalid Password'], 412); } } - diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 0cf124ebd9..27039fcb90 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -111,8 +111,9 @@ class ResetPasswordController extends Controller { auth()->logout(); - if(request()->has('react') || request()->hasHeader('X-React')) + if(request()->has('react') || request()->hasHeader('X-React')) { return redirect(config('ninja.react_url').'/#/login'); + } return redirect('/'); } @@ -130,11 +131,11 @@ class ResetPasswordController extends Controller return new JsonResponse(['message' => trans($response)], 200); } - if($request->hasHeader('X-REACT') || $request->has('react')){ + if($request->hasHeader('X-REACT') || $request->has('react')) { return redirect(config('ninja.react_url').'/#/login'); + } else { + return redirect('/#/login'); } - else - return redirect('/#/login'); return redirect($this->redirectPath()) ->with('status', trans($response)); diff --git a/app/Http/Controllers/Bank/YodleeController.php b/app/Http/Controllers/Bank/YodleeController.php index bf4f1fc368..30e322a748 100644 --- a/app/Http/Controllers/Bank/YodleeController.php +++ b/app/Http/Controllers/Bank/YodleeController.php @@ -12,13 +12,13 @@ namespace App\Http\Controllers\Bank; use App\Helpers\Bank\Yodlee\DTO\AccountSummary; -use Illuminate\Http\Request; -use App\Models\BankIntegration; use App\Helpers\Bank\Yodlee\Yodlee; use App\Http\Controllers\BaseController; -use App\Jobs\Bank\ProcessBankTransactions; -use App\Http\Requests\Yodlee\YodleeAuthRequest; use App\Http\Requests\Yodlee\YodleeAdminRequest; +use App\Http\Requests\Yodlee\YodleeAuthRequest; +use App\Jobs\Bank\ProcessBankTransactions; +use App\Models\BankIntegration; +use Illuminate\Http\Request; class YodleeController extends BaseController { @@ -100,69 +100,69 @@ class YodleeController extends BaseController } - /** - * Process Yodlee Refresh Webhook. - * - * - * @OA\Post( - * path="/api/v1/yodlee/refresh", - * operationId="yodleeRefreshWebhook", - * tags={"yodlee"}, - * summary="Processing webhooks from Yodlee", - * description="Notifies the system when a data point can be refreshed", - * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), - * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), - * @OA\Parameter(ref="#/components/parameters/include"), - * @OA\Response( - * response=200, - * description="", - * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), - * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), - * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), - * @OA\JsonContent(ref="#/components/schemas/Credit"), - * ), - * @OA\Response( - * response=422, - * description="Validation error", - * @OA\JsonContent(ref="#/components/schemas/ValidationError"), - * - * ), - * @OA\Response( - * response="default", - * description="Unexpected Error", - * @OA\JsonContent(ref="#/components/schemas/Error"), - * ), - * ) - */ + /** + * Process Yodlee Refresh Webhook. + * + * + * @OA\Post( + * path="/api/v1/yodlee/refresh", + * operationId="yodleeRefreshWebhook", + * tags={"yodlee"}, + * summary="Processing webhooks from Yodlee", + * description="Notifies the system when a data point can be refreshed", + * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Response( + * response=200, + * description="", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/Credit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ - /* - { - "event":{ - "info":"REFRESH.PROCESS_COMPLETED", - "loginName":"fri21", - "data":{ - "providerAccount":[ - { - "id":10995860, - "providerId":16441, - "isManual":false, - "createdDate":"2017-12-22T05:47:35Z", - "aggregationSource":"USER", - "status":"SUCCESS", - "requestId":"NSyMGo+R4dktywIu3hBIkc3PgWA=", - "dataset":[ - { - "name":"BASIC_AGG_DATA", - "additionalStatus":"AVAILABLE_DATA_RETRIEVED", - "updateEligibility":"ALLOW_UPDATE", - "lastUpdated":"2017-12-22T05:48:16Z", - "lastUpdateAttempt":"2017-12-22T05:48:16Z" - } - ] - } - ] + /* + { + "event":{ + "info":"REFRESH.PROCESS_COMPLETED", + "loginName":"fri21", + "data":{ + "providerAccount":[ + { + "id":10995860, + "providerId":16441, + "isManual":false, + "createdDate":"2017-12-22T05:47:35Z", + "aggregationSource":"USER", + "status":"SUCCESS", + "requestId":"NSyMGo+R4dktywIu3hBIkc3PgWA=", + "dataset":[ + { + "name":"BASIC_AGG_DATA", + "additionalStatus":"AVAILABLE_DATA_RETRIEVED", + "updateEligibility":"ALLOW_UPDATE", + "lastUpdated":"2017-12-22T05:48:16Z", + "lastUpdateAttempt":"2017-12-22T05:48:16Z" + } + ] + } + ] + } } - } }*/ public function refreshWebhook(Request $request) { @@ -177,28 +177,28 @@ class YodleeController extends BaseController // return response()->json(['message' => 'Unauthorized'], 403); } -/* -{ - "event":{ - "notificationId":"63c73475-4db5-49ef-8553-8303337ca7c3", - "info":"LATEST_BALANCE_UPDATES", - "loginName":"user1", - "data":{ - "providerAccountId":658552, - "latestBalanceEvent":[ - { - "accountId":12345, - "status":"SUCCESS" - }, - { - "accountId":12346, - "status":"FAILED" - } - ] - } - } -} -*/ + /* + { + "event":{ + "notificationId":"63c73475-4db5-49ef-8553-8303337ca7c3", + "info":"LATEST_BALANCE_UPDATES", + "loginName":"user1", + "data":{ + "providerAccountId":658552, + "latestBalanceEvent":[ + { + "accountId":12345, + "status":"SUCCESS" + }, + { + "accountId":12346, + "status":"FAILED" + } + ] + } + } + } + */ public function balanceWebhook(Request $request) { nlog("yodlee refresh"); @@ -211,29 +211,29 @@ class YodleeController extends BaseController // return response()->json(['message' => 'Unauthorized'], 403); } -/* -{ - "event":{ - "data":[ - { - "autoRefresh":{ - "additionalStatus":"SCHEDULED", - "status":"ENABLED" - }, - "accountIds":[ - 1112645899, - 1112645898 - ], - "loginName":"YSL1555332811628", - "providerAccountId":11381459 - } - ], - "notificationTime":"2019-06-14T04:49:39Z", - "notificationId":"4e672150-156048777", - "info":"AUTO_REFRESH_UPDATES" - } -} -*/ + /* + { + "event":{ + "data":[ + { + "autoRefresh":{ + "additionalStatus":"SCHEDULED", + "status":"ENABLED" + }, + "accountIds":[ + 1112645899, + 1112645898 + ], + "loginName":"YSL1555332811628", + "providerAccountId":11381459 + } + ], + "notificationTime":"2019-06-14T04:49:39Z", + "notificationId":"4e672150-156048777", + "info":"AUTO_REFRESH_UPDATES" + } + } + */ public function refreshUpdatesWebhook(Request $request) { //notifies a user if there are problems with yodlee accessing the data @@ -248,27 +248,27 @@ class YodleeController extends BaseController } -/* -"event": { - "notificationId": "64b7ed1a-1530523285", - "info": "DATA_UPDATES.USER_DATA", - "data": { - "userCount": 1, - "fromDate": "2017-11-10T10:18:44Z", - "toDate": "2017-11-10T11:18:43Z", - "userData": [{ - "user": { - "loginName": "YSL1484052178554" - }, - "links": [{ - "methodType": "GET", - "rel": "getUserData", - "href": "dataExtracts/userData?fromDate=2017-11-10T10:18:44Z&toDate=2017-11-10T11:18:43Z&loginName=YSL1484052178554" + /* + "event": { + "notificationId": "64b7ed1a-1530523285", + "info": "DATA_UPDATES.USER_DATA", + "data": { + "userCount": 1, + "fromDate": "2017-11-10T10:18:44Z", + "toDate": "2017-11-10T11:18:43Z", + "userData": [{ + "user": { + "loginName": "YSL1484052178554" + }, + "links": [{ + "methodType": "GET", + "rel": "getUserData", + "href": "dataExtracts/userData?fromDate=2017-11-10T10:18:44Z&toDate=2017-11-10T11:18:43Z&loginName=YSL1484052178554" + }] }] - }] + } } -} -*/ + */ public function dataUpdatesWebhook(Request $request) { //this is the main hook we use for notifications @@ -292,8 +292,9 @@ class YodleeController extends BaseController ->where('account_id', $account_number) ->exists(); - if(!$bank_integration) + if(!$bank_integration) { return response()->json(['message' => 'Account does not exist.'], 400); + } $yodlee = new Yodlee($user->account->bank_integration_account_id); diff --git a/app/Http/Controllers/BankIntegrationController.php b/app/Http/Controllers/BankIntegrationController.php index 3e404ff73f..b2d3a33a9a 100644 --- a/app/Http/Controllers/BankIntegrationController.php +++ b/app/Http/Controllers/BankIntegrationController.php @@ -11,26 +11,25 @@ namespace App\Http\Controllers; -use Illuminate\Http\Request; -use Illuminate\Http\Response; -use App\Models\BankIntegration; -use App\Utils\Traits\MakesHash; -use Illuminate\Http\JsonResponse; -use App\Helpers\Bank\Yodlee\Yodlee; -use Illuminate\Support\Facades\Cache; use App\Factory\BankIntegrationFactory; use App\Filters\BankIntegrationFilters; -use App\Jobs\Bank\ProcessBankTransactions; -use App\Repositories\BankIntegrationRepository; -use App\Transformers\BankIntegrationTransformer; +use App\Helpers\Bank\Yodlee\Yodlee; +use App\Http\Requests\BankIntegration\AdminBankIntegrationRequest; use App\Http\Requests\BankIntegration\BulkBankIntegrationRequest; +use App\Http\Requests\BankIntegration\CreateBankIntegrationRequest; +use App\Http\Requests\BankIntegration\DestroyBankIntegrationRequest; use App\Http\Requests\BankIntegration\EditBankIntegrationRequest; use App\Http\Requests\BankIntegration\ShowBankIntegrationRequest; -use App\Http\Requests\BankIntegration\AdminBankIntegrationRequest; use App\Http\Requests\BankIntegration\StoreBankIntegrationRequest; -use App\Http\Requests\BankIntegration\CreateBankIntegrationRequest; use App\Http\Requests\BankIntegration\UpdateBankIntegrationRequest; -use App\Http\Requests\BankIntegration\DestroyBankIntegrationRequest; +use App\Jobs\Bank\ProcessBankTransactions; +use App\Models\BankIntegration; +use App\Repositories\BankIntegrationRepository; +use App\Transformers\BankIntegrationTransformer; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Cache; class BankIntegrationController extends BaseController { @@ -109,7 +108,7 @@ class BankIntegrationController extends BaseController * @param CreateBankIntegrationRequest $request * @return Response * - * + * */ public function create(CreateBankIntegrationRequest $request) { @@ -210,12 +209,11 @@ class BankIntegrationController extends BaseController $accounts = $yodlee->getAccounts(); foreach ($accounts as $account) { - if ($bi = BankIntegration::withTrashed()->where('bank_account_id', $account['id'])->where('company_id', $user->company()->id)->first()){ - $bi->balance = $account['current_balance']; - $bi->currency = $account['account_currency']; - $bi->save(); - } - else { + if ($bi = BankIntegration::withTrashed()->where('bank_account_id', $account['id'])->where('company_id', $user->company()->id)->first()) { + $bi->balance = $account['current_balance']; + $bi->currency = $account['account_currency']; + $bi->save(); + } else { $bank_integration = new BankIntegration(); $bank_integration->company_id = $user->company()->id; $bank_integration->account_id = $user->account_id; @@ -293,7 +291,7 @@ class BankIntegrationController extends BaseController /** @var \App\Models\User $user */ $user = auth()->user(); - $user->account->bank_integrations->each(function ($bank_integration) use ($user){ + $user->account->bank_integrations->each(function ($bank_integration) use ($user) { (new ProcessBankTransactions($user->account->bank_integration_account_id, $bank_integration))->handle(); }); diff --git a/app/Http/Controllers/BankTransactionRuleController.php b/app/Http/Controllers/BankTransactionRuleController.php index a17cf4cfe7..b34043e48f 100644 --- a/app/Http/Controllers/BankTransactionRuleController.php +++ b/app/Http/Controllers/BankTransactionRuleController.php @@ -11,20 +11,20 @@ namespace App\Http\Controllers; -use App\Utils\Traits\MakesHash; -use App\Models\BankTransactionRule; use App\Factory\BankTransactionRuleFactory; use App\Filters\BankTransactionRuleFilters; -use App\Repositories\BankTransactionRuleRepository; -use App\Transformers\BankTransactionRuleTransformer; use App\Http\Requests\BankTransactionRule\BulkBankTransactionRuleRequest; +use App\Http\Requests\BankTransactionRule\CreateBankTransactionRuleRequest; +use App\Http\Requests\BankTransactionRule\DestroyBankTransactionRuleRequest; use App\Http\Requests\BankTransactionRule\EditBankTransactionRuleRequest; use App\Http\Requests\BankTransactionRule\ShowBankTransactionRuleRequest; use App\Http\Requests\BankTransactionRule\StoreBankTransactionRuleRequest; -use App\Http\Requests\BankTransactionRule\CreateBankTransactionRuleRequest; use App\Http\Requests\BankTransactionRule\UpdateBankTransactionRuleRequest; -use App\Http\Requests\BankTransactionRule\DestroyBankTransactionRuleRequest; +use App\Models\BankTransactionRule; +use App\Repositories\BankTransactionRuleRepository; use App\Services\Bank\BankMatchingService; +use App\Transformers\BankTransactionRuleTransformer; +use App\Utils\Traits\MakesHash; class BankTransactionRuleController extends BaseController { diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index a8f43eae85..2d5d41c24e 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -531,7 +531,7 @@ class BaseController extends Controller $paginator = $query->paginate($limit); /** @phpstan-ignore-next-line **/ - $query = $paginator->getCollection(); + $query = $paginator->getCollection(); $resource = new Collection($query, $transformer, $this->entity_type); @@ -889,7 +889,7 @@ class BaseController extends Controller $resource = new Collection($query, $transformer, $this->entity_type); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); - } + } // else { // $resource = new Collection($query, $transformer, $this->entity_type); @@ -924,10 +924,9 @@ class BaseController extends Controller if ($this->entity_type == BankIntegration::class && !$user->isSuperUser() && $user->hasIntersectPermissions(['create_bank_transaction','edit_bank_transaction','view_bank_transaction'])) { $query->exclude(["balance"]); } //allows us to selective display bank integrations back to the user if they can view / create bank transactions but without the bank balance being present in the response - elseif($this->entity_type == TaxRate::class && $user->hasIntersectPermissions(['create_invoice','edit_invoice','create_quote','edit_quote','create_purchase_order','edit_purchase_order'])){ + elseif($this->entity_type == TaxRate::class && $user->hasIntersectPermissions(['create_invoice','edit_invoice','create_quote','edit_quote','create_purchase_order','edit_purchase_order'])) { // need to show tax rates if the user has the ability to create documents. - } - else { + } else { $query->where('user_id', '=', $user->id); } } elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) { diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index 1dfff875d3..158688ba55 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -11,36 +11,36 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Client; -use App\Models\Account; -use App\Models\Company; -use App\Models\SystemLog; -use Postmark\PostmarkClient; -use Illuminate\Http\Response; -use App\Factory\ClientFactory; -use App\Filters\ClientFilters; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\Uploadable; -use App\Utils\Traits\BulkOptions; -use App\Jobs\Client\UpdateTaxData; -use App\Utils\Traits\SavesDocuments; -use App\Repositories\ClientRepository; use App\Events\Client\ClientWasCreated; use App\Events\Client\ClientWasUpdated; -use App\Transformers\ClientTransformer; -use Illuminate\Support\Facades\Storage; +use App\Factory\ClientFactory; +use App\Filters\ClientFilters; use App\Http\Requests\Client\BulkClientRequest; -use App\Http\Requests\Client\EditClientRequest; -use App\Http\Requests\Client\ShowClientRequest; -use App\Http\Requests\Client\PurgeClientRequest; -use App\Http\Requests\Client\StoreClientRequest; use App\Http\Requests\Client\CreateClientRequest; +use App\Http\Requests\Client\DestroyClientRequest; +use App\Http\Requests\Client\EditClientRequest; +use App\Http\Requests\Client\PurgeClientRequest; +use App\Http\Requests\Client\ReactivateClientEmailRequest; +use App\Http\Requests\Client\ShowClientRequest; +use App\Http\Requests\Client\StoreClientRequest; use App\Http\Requests\Client\UpdateClientRequest; use App\Http\Requests\Client\UploadClientRequest; -use App\Http\Requests\Client\DestroyClientRequest; -use App\Http\Requests\Client\ReactivateClientEmailRequest; +use App\Jobs\Client\UpdateTaxData; use App\Jobs\PostMark\ProcessPostmarkWebhook; +use App\Models\Account; +use App\Models\Client; +use App\Models\Company; +use App\Models\SystemLog; +use App\Repositories\ClientRepository; +use App\Transformers\ClientTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\BulkOptions; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use App\Utils\Traits\Uploadable; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Storage; +use Postmark\PostmarkClient; /** * Class ClientController. @@ -74,10 +74,10 @@ class ClientController extends BaseController } /** - * + * * @param ClientFilters $filters * @return Response - * + * */ public function index(ClientFilters $filters) { @@ -275,15 +275,15 @@ class ClientController extends BaseController //todo add an event here using the client name as reference for purge event } -/** - * Update the specified resource in storage. - * - * @param PurgeClientRequest $request - * @param Client $client - * @param string $mergeable_client - * @return \Illuminate\Http\JsonResponse - * - */ + /** + * Update the specified resource in storage. + * + * @param PurgeClientRequest $request + * @param Client $client + * @param string $mergeable_client + * @return \Illuminate\Http\JsonResponse + * + */ public function merge(PurgeClientRequest $request, Client $client, string $mergeable_client) { @@ -313,8 +313,9 @@ class ClientController extends BaseController */ public function updateTaxData(PurgeClientRequest $request, Client $client) { - if($client->company->account->isPaid()) + if($client->company->account->isPaid()) { (new UpdateTaxData($client, $client->company))->handle(); + } return $this->itemResponse($client->fresh()); } @@ -331,8 +332,8 @@ class ClientController extends BaseController /** @var \App\Models\User $user */ $user = auth()->user(); - if(stripos($bounce_id, '-') !== false){ - $log = + if(stripos($bounce_id, '-') !== false) { + $log = SystemLog::query() ->where('company_id', $user->company()->id) ->where('type_id', SystemLog::TYPE_WEBHOOK_RESPONSE) @@ -343,16 +344,16 @@ class ClientController extends BaseController $resolved_bounce_id = false; - if($log && ($log?->log['ID'] ?? false)){ + if($log && ($log?->log['ID'] ?? false)) { $resolved_bounce_id = $log->log['ID'] ?? false; } - if(!$resolved_bounce_id){ + if(!$resolved_bounce_id) { $ppwebhook = new ProcessPostmarkWebhook([]); $resolved_bounce_id = $ppwebhook->getBounceId($bounce_id); } - if(!$resolved_bounce_id){ + if(!$resolved_bounce_id) { return response()->json(['message' => 'Bounce ID not found'], 400); } @@ -367,8 +368,7 @@ class ClientController extends BaseController return response()->json(['message' => 'Success'], 200); - } - catch(\Exception $e){ + } catch(\Exception $e) { return response()->json(['message' => $e->getMessage(), 400]); diff --git a/app/Http/Controllers/ClientPortal/ContactHashLoginController.php b/app/Http/Controllers/ClientPortal/ContactHashLoginController.php index 8501131833..abcef260ff 100644 --- a/app/Http/Controllers/ClientPortal/ContactHashLoginController.php +++ b/app/Http/Controllers/ClientPortal/ContactHashLoginController.php @@ -11,11 +11,10 @@ namespace App\Http\Controllers\ClientPortal; -use Auth; -use App\Models\RecurringInvoice; use App\Http\Controllers\Controller; -use Illuminate\Support\Facades\Redirect; use App\Http\ViewComposers\PortalComposer; +use App\Models\RecurringInvoice; +use Illuminate\Support\Facades\Redirect; class ContactHashLoginController extends Controller { diff --git a/app/Http/Controllers/ClientPortal/EntityViewController.php b/app/Http/Controllers/ClientPortal/EntityViewController.php deleted file mode 100644 index f5c40de3a3..0000000000 --- a/app/Http/Controllers/ClientPortal/EntityViewController.php +++ /dev/null @@ -1,184 +0,0 @@ -entity_types)) { - abort(404, 'Entity not found'); - } - - $invitation_entity = sprintf('App\\Models\\%sInvitation', ucfirst($entity_type)); - - $key = $entity_type.'_id'; - - $invitation = $invitation_entity::where('key', $invitation_key) - ->with('contact.client') - ->firstOrFail(); - - $contact = $invitation->contact; - $client = $contact->client; - $entity = $invitation->{$entity_type}; - - if (is_null($contact->password) || empty($contact->password)) { - return redirect("/client/password/reset?email={$contact->email}"); - } - - if ((bool) $invitation->contact->client->getSetting('enable_client_portal_password') !== false) { - session()->flash("{$entity_type}_VIEW_{$entity->hashed_id}", true); - } - - if (! session("{$entity_type}_VIEW_{$entity->hashed_id}")) { - return redirect()->route('client.entity_view.password', compact('entity_type', 'invitation_key')); - } - - return $this->render('view_entity.index', [ - 'root' => 'themes', - 'entity' => $entity, - ]); - } - - /** - * Show the form for entering password. - * - * @param string $entity_type - * @param string $invitation_key - * - * @return Factory|View - */ - public function password(string $entity_type, string $invitation_key) - { - return $this->render('view_entity.password', [ - 'root' => 'themes', - 'entity_type' => $entity_type, - ]); - } - - /**` - * Handle the password check. - * - * @param string $entity_type - * @param string $invitation_key - * - * @return Redirector|RedirectResponse|mixed - */ - public function handlePassword(string $entity_type, string $invitation_key) - { - if (! in_array($entity_type, $this->entity_types)) { - abort(404, 'Entity not found'); - } - - $invitation_entity = sprintf('App\\Models\\%sInvitation', ucfirst($entity_type)); - - $key = $entity_type.'_id'; - - $invitation = $invitation_entity::where('key', $invitation_key)->firstOrFail(); - - $contact = $invitation->contact; - - $check = Hash::check(request()->password, $contact->password); - - $entity_class = sprintf('App\\Models\\%s', ucfirst($entity_type)); - - $entity = $entity_class::findOrFail($invitation->{$key}); - - if ($check) { - session()->flash("{$entity_type}_VIEW_{$entity->hashed_id}", true); - - return redirect()->route('client.entity_view', compact('entity_type', 'invitation_key')); - } - - session()->flash('PASSWORD_FAILED', true); - - return back(); - } - - public function handlePasswordSet(Request $request) - { - $entity_obj = 'App\Models\\'.ucfirst(Str::camel($request->entity_type)).'Invitation'; - $key = $request->entity_type.'_id'; - - $invitation = $entity_obj::where('key', $request->invitation_key) - ->whereHas($request->entity_type, function ($query) { - $query->where('is_deleted', 0); - }) - ->with('contact.client') - ->firstOrFail(); - - $contact = $invitation->contact; - $contact->password = Hash::make($request->password); - $contact->save(); - - $request->session()->invalidate(); - auth()->guard('contact')->loginUsingId($contact->id, true); - - if (! $invitation->viewed_date) { - $invitation->markViewed(); - - if (! session()->get('is_silent')) { - event(new InvitationWasViewed($invitation->{$request->entity_type}, $invitation, $invitation->{$request->entity_type}->company, Ninja::eventVars())); - } - - if (! session()->get('is_silent')) { - $this->fireEntityViewedEvent($invitation, $request->entity_type); - } - } - - return redirect()->route('client.'.$request->entity_type.'.show', [$request->entity_type => $this->encodePrimaryKey($invitation->{$key})]); - } - - private function fireEntityViewedEvent($invitation, $entity_string) - { - switch ($entity_string) { - case 'invoice': - event(new InvoiceWasViewed($invitation, $invitation->company, Ninja::eventVars())); - break; - case 'quote': - event(new QuoteWasViewed($invitation, $invitation->company, Ninja::eventVars())); - break; - case 'credit': - event(new CreditWasViewed($invitation, $invitation->company, Ninja::eventVars())); - break; - default: - // code... - break; - } - } -} diff --git a/app/Http/Controllers/ClientPortal/InvitationController.php b/app/Http/Controllers/ClientPortal/InvitationController.php index e5007cca9a..8f62169b0e 100644 --- a/app/Http/Controllers/ClientPortal/InvitationController.php +++ b/app/Http/Controllers/ClientPortal/InvitationController.php @@ -11,27 +11,27 @@ namespace App\Http\Controllers\ClientPortal; -use App\Utils\Ninja; -use App\Models\Client; -use App\Models\Payment; -use Illuminate\Support\Str; -use Illuminate\Http\Request; -use App\Models\ClientContact; -use App\Models\QuoteInvitation; -use App\Utils\Traits\MakesHash; -use App\Models\CreditInvitation; -use App\Utils\Traits\MakesDates; -use App\Jobs\Entity\CreateRawPdf; -use App\Models\InvoiceInvitation; -use App\Events\Quote\QuoteWasViewed; -use App\Http\Controllers\Controller; -use Illuminate\Support\Facades\Auth; -use App\Events\Credit\CreditWasViewed; use App\Events\Contact\ContactLoggedIn; -use App\Models\PurchaseOrderInvitation; +use App\Events\Credit\CreditWasViewed; use App\Events\Invoice\InvoiceWasViewed; use App\Events\Misc\InvitationWasViewed; +use App\Events\Quote\QuoteWasViewed; +use App\Http\Controllers\Controller; +use App\Jobs\Entity\CreateRawPdf; +use App\Models\ClientContact; +use App\Models\CreditInvitation; +use App\Models\InvoiceInvitation; +use App\Models\Payment; +use App\Models\PurchaseOrderInvitation; +use App\Models\QuoteInvitation; use App\Services\ClientPortal\InstantPayment; +use App\Utils\Ninja; +use App\Utils\Traits\MakesDates; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Str; /** * Class InvitationController. @@ -100,7 +100,7 @@ class InvitationController extends Controller if (empty($client_contact->email)) { $client_contact->email = Str::random(15) . "@example.com"; $client_contact->save(); - } + } if (request()->has('client_hash') && request()->input('client_hash') == $invitation->contact->client->client_hash) { request()->session()->invalidate(); @@ -195,7 +195,7 @@ class InvitationController extends Controller $file_name = $invitation->{$entity}->numberFormatter().'.pdf'; - $file = (new CreateRawPdf($invitation, $invitation->company->db))->handle(); + $file = (new CreateRawPdf($invitation))->handle(); $headers = ['Content-Type' => 'application/pdf']; @@ -212,6 +212,41 @@ class InvitationController extends Controller { } + + public function handlePasswordSet(Request $request) + { + $entity_obj = 'App\Models\\'.ucfirst(Str::camel($request->entity_type)).'Invitation'; + $key = $request->entity_type.'_id'; + + $invitation = $entity_obj::where('key', $request->invitation_key) + ->whereHas($request->entity_type, function ($query) { + $query->where('is_deleted', 0); + }) + ->with('contact.client') + ->firstOrFail(); + + $contact = $invitation->contact; + $contact->password = Hash::make($request->password); + $contact->save(); + + $request->session()->invalidate(); + auth()->guard('contact')->loginUsingId($contact->id, true); + + if (! $invitation->viewed_date) { + $invitation->markViewed(); + + if (! session()->get('is_silent')) { + event(new InvitationWasViewed($invitation->{$request->entity_type}, $invitation, $invitation->{$request->entity_type}->company, Ninja::eventVars())); + } + + if (! session()->get('is_silent')) { + $this->fireEntityViewedEvent($invitation, $request->entity_type); + } + } + + return redirect()->route('client.'.$request->entity_type.'.show', [$request->entity_type => $this->encodePrimaryKey($invitation->{$key})]); + } + public function paymentRouter(string $contact_key, string $payment_id) { /** @var \App\Models\ClientContact $contact **/ diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index bbed2ee5bb..e293eacbbd 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -11,29 +11,27 @@ namespace App\Http\Controllers\ClientPortal; -use App\Utils\Ninja; -use App\Utils\Number; -use App\Models\Invoice; -use Illuminate\View\View; -use Illuminate\Http\Request; -use App\Models\QuoteInvitation; -use App\Utils\Traits\MakesHash; -use App\Models\CreditInvitation; -use App\Utils\Traits\MakesDates; -use App\Models\InvoiceInvitation; -use App\Http\Controllers\Controller; -use Illuminate\Http\RedirectResponse; -use Illuminate\Support\Facades\Cache; -use Illuminate\Contracts\View\Factory; -use App\Models\PurchaseOrderInvitation; -use Illuminate\Support\Facades\Storage; use App\Events\Invoice\InvoiceWasViewed; use App\Events\Misc\InvitationWasViewed; -use App\Models\RecurringInvoiceInvitation; -use App\Jobs\Vendor\CreatePurchaseOrderPdf; +use App\Http\Controllers\Controller; +use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest; use App\Http\Requests\ClientPortal\Invoices\ShowInvoiceRequest; use App\Http\Requests\ClientPortal\Invoices\ShowInvoicesRequest; -use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest; +use App\Models\CreditInvitation; +use App\Models\Invoice; +use App\Models\InvoiceInvitation; +use App\Models\QuoteInvitation; +use App\Models\RecurringInvoiceInvitation; +use App\Utils\Ninja; +use App\Utils\Number; +use App\Utils\Traits\MakesDates; +use App\Utils\Traits\MakesHash; +use Illuminate\Contracts\View\Factory; +use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Storage; +use Illuminate\View\View; class InvoiceController extends Controller { @@ -88,14 +86,14 @@ class InvoiceController extends Controller { $data = Cache::get($hash); - if(!$data){ + if(!$data) { usleep(200000); $data = Cache::get($hash); } $invitation = false; - match($data['entity_type'] ?? false){ + match($data['entity_type'] ?? false) { 'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']), 'quote' => $invitation = QuoteInvitation::withTrashed()->find($data['invitation_id']), 'credit' => $invitation = CreditInvitation::withTrashed()->find($data['invitation_id']), @@ -107,7 +105,7 @@ class InvoiceController extends Controller return redirect('/'); } - $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle(); + $file = (new \App\Jobs\Entity\CreateRawPdf($invitation))->handle(); $headers = ['Content-Type' => 'application/pdf']; return response()->make($file, 200, $headers); diff --git a/app/Http/Controllers/ClientPortal/PaymentController.php b/app/Http/Controllers/ClientPortal/PaymentController.php index 841a61a105..81b560ab19 100644 --- a/app/Http/Controllers/ClientPortal/PaymentController.php +++ b/app/Http/Controllers/ClientPortal/PaymentController.php @@ -27,7 +27,6 @@ use App\Services\Subscription\SubscriptionService; use App\Utils\Traits\MakesDates; use App\Utils\Traits\MakesHash; use Illuminate\Contracts\View\Factory; -use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\View\View; diff --git a/app/Http/Controllers/ClientPortal/QuoteController.php b/app/Http/Controllers/ClientPortal/QuoteController.php index 39d48aab29..98cb3cd871 100644 --- a/app/Http/Controllers/ClientPortal/QuoteController.php +++ b/app/Http/Controllers/ClientPortal/QuoteController.php @@ -12,22 +12,21 @@ namespace App\Http\Controllers\ClientPortal; -use App\Utils\Ninja; -use App\Models\Quote; -use Illuminate\View\View; -use Illuminate\Http\Request; -use App\Models\QuoteInvitation; -use App\Utils\Traits\MakesHash; +use App\Events\Misc\InvitationWasViewed; use App\Events\Quote\QuoteWasViewed; use App\Http\Controllers\Controller; -use App\Jobs\Invoice\InjectSignature; -use Illuminate\Contracts\View\Factory; -use Illuminate\Support\Facades\Storage; -use App\Events\Misc\InvitationWasViewed; -use Symfony\Component\HttpFoundation\BinaryFileResponse; +use App\Http\Requests\ClientPortal\Quotes\ProcessQuotesInBulkRequest; use App\Http\Requests\ClientPortal\Quotes\ShowQuoteRequest; use App\Http\Requests\ClientPortal\Quotes\ShowQuotesRequest; -use App\Http\Requests\ClientPortal\Quotes\ProcessQuotesInBulkRequest; +use App\Jobs\Invoice\InjectSignature; +use App\Models\Quote; +use App\Models\QuoteInvitation; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use Illuminate\Contracts\View\Factory; +use Illuminate\Http\Request; +use Illuminate\View\View; +use Symfony\Component\HttpFoundation\BinaryFileResponse; class QuoteController extends Controller { @@ -123,7 +122,7 @@ class QuoteController extends Controller $client_contact = auth()->user(); $quote_invitations = QuoteInvitation::query() - ->with('quote','company') + ->with('quote', 'company') ->whereIn('quote_id', $ids) ->where('client_contact_id', $client_contact->id) ->withTrashed() @@ -137,7 +136,7 @@ class QuoteController extends Controller if ($quote_invitations->count() == 1) { $invitation = $quote_invitations->first(); - $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle(); + $file = (new \App\Jobs\Entity\CreateRawPdf($invitation))->handle(); return response()->streamDownload(function () use ($file) { echo $file; }, $invitation->quote->numberFormatter().".pdf", ['Content-Type' => 'application/pdf']); @@ -152,7 +151,7 @@ class QuoteController extends Controller $zipFile = new \PhpZip\ZipFile(); try { foreach ($quote_invitations as $invitation) { - $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle(); + $file = (new \App\Jobs\Entity\CreateRawPdf($invitation))->handle(); $zipFile->addFromString($invitation->quote->numberFormatter() . '.pdf', $file); } diff --git a/app/Http/Controllers/ClientPortal/StatementController.php b/app/Http/Controllers/ClientPortal/StatementController.php index 7ed81d48fe..d5bbafb024 100644 --- a/app/Http/Controllers/ClientPortal/StatementController.php +++ b/app/Http/Controllers/ClientPortal/StatementController.php @@ -23,7 +23,7 @@ class StatementController extends Controller /** * Show the statement in the client portal. * - * @return \Illuminate\View\View + * @return \Illuminate\View\View */ public function index(): View { diff --git a/app/Http/Controllers/ClientPortal/TempRouteController.php b/app/Http/Controllers/ClientPortal/TempRouteController.php index b1f71a8370..4efe5b9b63 100644 --- a/app/Http/Controllers/ClientPortal/TempRouteController.php +++ b/app/Http/Controllers/ClientPortal/TempRouteController.php @@ -11,7 +11,6 @@ namespace App\Http\Controllers\ClientPortal; -use Auth; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Redirect; diff --git a/app/Http/Controllers/ClientStatementController.php b/app/Http/Controllers/ClientStatementController.php index 13d4a81ff0..fe10335b81 100644 --- a/app/Http/Controllers/ClientStatementController.php +++ b/app/Http/Controllers/ClientStatementController.php @@ -11,10 +11,10 @@ namespace App\Http\Controllers; +use App\Http\Requests\Statements\CreateStatementRequest; use App\Utils\Traits\MakesHash; use App\Utils\Traits\Pdf\PdfMaker; use Illuminate\Support\Facades\Response; -use App\Http\Requests\Statements\CreateStatementRequest; class ClientStatementController extends BaseController { @@ -43,7 +43,7 @@ class ClientStatementController extends BaseController } $pdf = $request->client()->service()->statement( - $request->only(['start_date', 'end_date', 'show_payments_table', 'show_aging_table', 'status', 'show_credits_table']), + $request->only(['start_date', 'end_date', 'show_payments_table', 'show_aging_table', 'status', 'show_credits_table', 'template']), $send_email ); diff --git a/app/Http/Controllers/CompanyController.php b/app/Http/Controllers/CompanyController.php index ede5c1b92d..6c476ab979 100644 --- a/app/Http/Controllers/CompanyController.php +++ b/app/Http/Controllers/CompanyController.php @@ -11,39 +11,38 @@ namespace App\Http\Controllers; -use Str; -use App\Utils\Ninja; -use App\Models\Account; -use App\Models\Company; -use App\Models\CompanyUser; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\Uploadable; -use App\Jobs\Mail\NinjaMailerJob; -use App\DataMapper\CompanySettings; -use App\Jobs\Company\CreateCompany; -use App\Jobs\Company\CompanyTaxRate; -use App\Jobs\Mail\NinjaMailerObject; -use App\Mail\Company\CompanyDeleted; -use App\Utils\Traits\SavesDocuments; -use Turbo124\Beacon\Facades\LightLogs; -use App\Repositories\CompanyRepository; -use Illuminate\Support\Facades\Storage; -use App\Jobs\Company\CreateCompanyToken; -use App\Transformers\CompanyTransformer; use App\DataMapper\Analytics\AccountDeleted; -use App\Transformers\CompanyUserTransformer; -use Illuminate\Foundation\Bus\DispatchesJobs; -use App\Jobs\Company\CreateCompanyPaymentTerms; -use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\DataMapper\CompanySettings; +use App\Http\Requests\Company\CreateCompanyRequest; +use App\Http\Requests\Company\DefaultCompanyRequest; +use App\Http\Requests\Company\DestroyCompanyRequest; use App\Http\Requests\Company\EditCompanyRequest; use App\Http\Requests\Company\ShowCompanyRequest; use App\Http\Requests\Company\StoreCompanyRequest; -use App\Http\Requests\Company\CreateCompanyRequest; use App\Http\Requests\Company\UpdateCompanyRequest; use App\Http\Requests\Company\UploadCompanyRequest; -use App\Http\Requests\Company\DefaultCompanyRequest; -use App\Http\Requests\Company\DestroyCompanyRequest; +use App\Jobs\Company\CompanyTaxRate; +use App\Jobs\Company\CreateCompany; +use App\Jobs\Company\CreateCompanyPaymentTerms; +use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\Jobs\Company\CreateCompanyToken; +use App\Jobs\Mail\NinjaMailerJob; +use App\Jobs\Mail\NinjaMailerObject; +use App\Mail\Company\CompanyDeleted; +use App\Models\Account; +use App\Models\Company; +use App\Models\CompanyUser; +use App\Repositories\CompanyRepository; +use App\Transformers\CompanyTransformer; +use App\Transformers\CompanyUserTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use App\Utils\Traits\Uploadable; +use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Storage; +use Turbo124\Beacon\Facades\LightLogs; /** * Class CompanyController. @@ -427,7 +426,7 @@ class CompanyController extends BaseController $this->saveDocuments($request->input('documents'), $company, $request->input('is_public', true)); } - if($request->has('e_invoice_certificate') && !is_null($request->file("e_invoice_certificate"))){ + if($request->has('e_invoice_certificate') && !is_null($request->file("e_invoice_certificate"))) { $company->e_invoice_certificate = base64_encode($request->file("e_invoice_certificate")->get()); @@ -684,16 +683,15 @@ class CompanyController extends BaseController 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 { (new CompanyTaxRate($company))->handle(); } catch(\Exception $e) { return response()->json(['message' => 'There was a problem updating the tax rates. Please try again.'], 400); } - } - else + } else { return response()->json(['message' => 'Tax configuration not available due to settings / plan restriction.'], 400); + } return $this->itemResponse($company->fresh()); } @@ -707,7 +705,7 @@ class CompanyController extends BaseController $logo = strlen($company->settings->company_logo) > 5 ? $company->settings->company_logo : 'https://pdf.invoicing.co/favicon-v2.png'; $headers = ['Content-Disposition' => 'inline']; - return response()->streamDownload(function () use ($logo){ + return response()->streamDownload(function () use ($logo) { echo @file_get_contents($logo); }, 'logo.png', $headers); diff --git a/app/Http/Controllers/CompanyGatewayController.php b/app/Http/Controllers/CompanyGatewayController.php index 5e9fed6bfd..9914327f52 100644 --- a/app/Http/Controllers/CompanyGatewayController.php +++ b/app/Http/Controllers/CompanyGatewayController.php @@ -213,8 +213,7 @@ class CompanyGatewayController extends BaseController if (in_array($company_gateway->gateway_key, $this->stripe_keys)) { StripeWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id); - } - 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); } diff --git a/app/Http/Controllers/CompanyUserController.php b/app/Http/Controllers/CompanyUserController.php index 69de122d5f..e020807da7 100644 --- a/app/Http/Controllers/CompanyUserController.php +++ b/app/Http/Controllers/CompanyUserController.php @@ -11,14 +11,14 @@ namespace App\Http\Controllers; -use App\Models\User; -use App\Models\CompanyUser; -use Illuminate\Http\Response; -use App\Transformers\UserTransformer; -use App\Transformers\CompanyUserTransformer; -use Illuminate\Database\Eloquent\ModelNotFoundException; -use App\Http\Requests\CompanyUser\UpdateCompanyUserRequest; use App\Http\Requests\CompanyUser\UpdateCompanyUserPreferencesRequest; +use App\Http\Requests\CompanyUser\UpdateCompanyUserRequest; +use App\Models\CompanyUser; +use App\Models\User; +use App\Transformers\CompanyUserTransformer; +use App\Transformers\UserTransformer; +use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Http\Response; class CompanyUserController extends BaseController { @@ -115,7 +115,7 @@ class CompanyUserController extends BaseController $auth_user = auth()->user(); $company = $auth_user->company(); - $company_user = CompanyUser::query()->where('user_id', $user->id)->where('company_id',$company->id)->first(); + $company_user = CompanyUser::query()->where('user_id', $user->id)->where('company_id', $company->id)->first(); if (! $company_user) { throw new ModelNotFoundException(ctrans('texts.company_user_not_found')); diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index b2be03691e..24db27876e 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -11,35 +11,35 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Client; -use App\Models\Credit; -use App\Models\Account; -use App\Models\Invoice; -use Illuminate\Http\Response; -use App\Factory\CreditFactory; -use App\Filters\CreditFilters; -use App\Jobs\Credit\ZipCredits; -use App\Utils\Traits\MakesHash; -use App\Jobs\Entity\EmailEntity; -use App\Factory\CloneCreditFactory; -use App\Services\PdfMaker\PdfMerge; -use Illuminate\Support\Facades\App; -use App\Utils\Traits\SavesDocuments; -use App\Repositories\CreditRepository; use App\Events\Credit\CreditWasCreated; use App\Events\Credit\CreditWasUpdated; -use App\Transformers\CreditTransformer; -use Illuminate\Support\Facades\Storage; +use App\Factory\CloneCreditFactory; +use App\Factory\CreditFactory; +use App\Filters\CreditFilters; +use App\Http\Requests\Credit\ActionCreditRequest; use App\Http\Requests\Credit\BulkCreditRequest; +use App\Http\Requests\Credit\CreateCreditRequest; +use App\Http\Requests\Credit\DestroyCreditRequest; use App\Http\Requests\Credit\EditCreditRequest; use App\Http\Requests\Credit\ShowCreditRequest; use App\Http\Requests\Credit\StoreCreditRequest; -use App\Http\Requests\Credit\ActionCreditRequest; -use App\Http\Requests\Credit\CreateCreditRequest; use App\Http\Requests\Credit\UpdateCreditRequest; use App\Http\Requests\Credit\UploadCreditRequest; -use App\Http\Requests\Credit\DestroyCreditRequest; +use App\Jobs\Credit\ZipCredits; +use App\Jobs\Entity\EmailEntity; +use App\Models\Account; +use App\Models\Client; +use App\Models\Credit; +use App\Models\Invoice; +use App\Repositories\CreditRepository; +use App\Services\PdfMaker\PdfMerge; +use App\Transformers\CreditTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Storage; /** * Class CreditController. @@ -386,7 +386,7 @@ class CreditController extends BaseController $credit->service() ->triggeredActions($request); - // ->deletePdf(); + // ->deletePdf(); /** @var \App\Models\User $user**/ $user = auth()->user(); @@ -527,20 +527,20 @@ class CreditController extends BaseController */ if ($action == 'bulk_download' && $credits->count() > 1) { - $credits->each(function ($credit) use($user){ + $credits->each(function ($credit) use ($user) { if ($user->cannot('view', $credit)) { return response()->json(['message' => ctrans('text.access_denied')]); } }); - ZipCredits::dispatch($credits->pluck('id')->toArray(), $credits->first()->company, $user); + ZipCredits::dispatch($credits->pluck('id')->toArray(), $user->company(), $user); return response()->json(['message' => ctrans('texts.sent_message')], 200); } if ($action == 'bulk_print' && $user->can('view', $credits->first())) { $paths = $credits->map(function ($credit) { - return (new \App\Jobs\Entity\CreateRawPdf($credit->invitations->first(), $credit->company->db))->handle(); + return (new \App\Jobs\Entity\CreateRawPdf($credit->invitations->first()))->handle(); }); $merge = (new PdfMerge($paths->toArray()))->run(); @@ -593,8 +593,8 @@ class CreditController extends BaseController $file = $credit->service()->getCreditPdf($credit->invitations->first()); return response()->streamDownload(function () use ($file) { - echo Storage::get($file); - }, basename($file), ['Content-Type' => 'application/pdf']); + echo $file; + }, $credit->numberFormatter().'.pdf', ['Content-Type' => 'application/pdf']); break; case 'archive': $this->credit_repository->archive($credit); @@ -710,8 +710,9 @@ class CreditController extends BaseController } return response()->streamDownload(function () use ($file) { - echo Storage::get($file); - }, basename($file), $headers); + echo $file; + }, $credit->numberFormatter().'.pdf', $headers); + } /** diff --git a/app/Http/Controllers/DesignController.php b/app/Http/Controllers/DesignController.php index 3e97a8c609..9f537f6e44 100644 --- a/app/Http/Controllers/DesignController.php +++ b/app/Http/Controllers/DesignController.php @@ -301,7 +301,10 @@ class DesignController extends BaseController */ public function create(CreateDesignRequest $request) { - $design = DesignFactory::create(auth()->user()->company()->id, auth()->user()->id); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $design = DesignFactory::create($user->company()->id, $user->id); return $this->itemResponse($design); } @@ -346,7 +349,11 @@ class DesignController extends BaseController */ public function store(StoreDesignRequest $request) { - $design = DesignFactory::create(auth()->user()->company()->id, auth()->user()->id); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $design = DesignFactory::create($user->company()->id, $user->id); + $design->fill($request->all()); $design->save(); diff --git a/app/Http/Controllers/DocumentController.php b/app/Http/Controllers/DocumentController.php index 70d4b1e8a1..9d822aee13 100644 --- a/app/Http/Controllers/DocumentController.php +++ b/app/Http/Controllers/DocumentController.php @@ -145,7 +145,7 @@ class DocumentController extends BaseController * @return Response */ public function update(UpdateDocumentRequest $request, Document $document) - { + { $document->fill($request->all()); $document->save(); diff --git a/app/Http/Controllers/EmailHistoryController.php b/app/Http/Controllers/EmailHistoryController.php index f29f1a79bd..493becc50d 100644 --- a/app/Http/Controllers/EmailHistoryController.php +++ b/app/Http/Controllers/EmailHistoryController.php @@ -33,7 +33,7 @@ class EmailHistoryController extends BaseController ->cursor() ->filter(function ($system_log) { return (isset($system_log->log['history']) && isset($system_log->log['history']['events']) && count($system_log->log['history']['events']) >=1) !== false; - })->map(function ($system_log) { + })->map(function ($system_log) { return $system_log->log['history']; })->values()->all(); @@ -59,7 +59,7 @@ class EmailHistoryController extends BaseController ->cursor() ->filter(function ($system_log) { return ($system_log->log['history'] && isset($system_log->log['history']['events']) && count($system_log->log['history']['events']) >=1) !== false; - })->map(function ($system_log) { + })->map(function ($system_log) { return $system_log->log['history']; })->values()->all(); diff --git a/app/Http/Controllers/ExpenseCategoryController.php b/app/Http/Controllers/ExpenseCategoryController.php index 36c47b9ba1..0c43f649aa 100644 --- a/app/Http/Controllers/ExpenseCategoryController.php +++ b/app/Http/Controllers/ExpenseCategoryController.php @@ -24,7 +24,6 @@ use App\Models\ExpenseCategory; use App\Repositories\BaseRepository; use App\Transformers\ExpenseCategoryTransformer; use App\Utils\Traits\MakesHash; -use Illuminate\Http\Request; use Illuminate\Http\Response; /** @@ -138,7 +137,7 @@ class ExpenseCategoryController extends BaseController /** * Store a newly created resource in storage. * - * @param StoreExpenseCategoryRequest $request + * @param StoreExpenseCategoryRequest $request * @return Response * * diff --git a/app/Http/Controllers/ExportController.php b/app/Http/Controllers/ExportController.php index f459a27333..55038c9895 100644 --- a/app/Http/Controllers/ExportController.php +++ b/app/Http/Controllers/ExportController.php @@ -11,12 +11,12 @@ namespace App\Http\Controllers; -use Illuminate\Support\Str; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Company\CompanyExport; -use Illuminate\Support\Facades\Cache; use App\Http\Requests\Export\StoreExportRequest; +use App\Jobs\Company\CompanyExport; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Str; class ExportController extends BaseController { diff --git a/app/Http/Controllers/GroupSettingController.php b/app/Http/Controllers/GroupSettingController.php index ff22b55242..cdd3d94c50 100644 --- a/app/Http/Controllers/GroupSettingController.php +++ b/app/Http/Controllers/GroupSettingController.php @@ -140,8 +140,9 @@ class GroupSettingController extends BaseController public function update(UpdateGroupSettingRequest $request, GroupSetting $group_setting) { /** Need this to prevent settings from being overwritten */ - if(!$request->file('company_logo')) + if(!$request->file('company_logo')) { $group_setting = $this->group_setting_repo->save($request->all(), $group_setting); + } $this->uploadLogo($request->file('company_logo'), $group_setting->company, $group_setting); diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 2871bc41e7..e8b82a4859 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -108,7 +108,7 @@ class ImportController extends Controller { $hints = []; - $translated_keys = collect($available_keys)->map(function ($value,$key){ + $translated_keys = collect($available_keys)->map(function ($value, $key) { $parts = explode(".", $value); $index = $parts[0]; @@ -121,16 +121,14 @@ class ImportController extends Controller foreach($headers as $key => $value) { - foreach($translated_keys as $tkey => $tvalue) - { + foreach($translated_keys as $tkey => $tvalue) { if($this->testMatch($value, $tvalue['label'])) { $hit = $tvalue['key']; $hints[$key] = $hit; unset($translated_keys[$tkey]); break; - } - else { + } else { $hints[$key] = null; } @@ -140,14 +138,12 @@ class ImportController extends Controller } //second pass using the index of the translation here - foreach($headers as $key => $value) - { + foreach($headers as $key => $value) { if(isset($hints[$key])) { continue; } - foreach($translated_keys as $tkey => $tvalue) - { + foreach($translated_keys as $tkey => $tvalue) { if($this->testMatch($value, $tvalue['index'])) { $hit = $tvalue['key']; $hints[$key] = $hit; @@ -164,7 +160,7 @@ class ImportController extends Controller } private function testMatch($haystack, $needle): bool - { + { return stripos($haystack, $needle) !== false; } @@ -256,7 +252,7 @@ class ImportController extends Controller if (substr_count(strstr($csvfile, "\n", true), $delimiter) >= $count) { $count = substr_count(strstr($csvfile, "\n", true), $delimiter); - $bestDelimiter = $delimiter; + $bestDelimiter = $delimiter; } } diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 2eca29cedd..22a1fdcb37 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -12,39 +12,40 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Quote; -use App\Models\Account; -use App\Models\Invoice; -use App\Jobs\Cron\AutoBill; -use Illuminate\Http\Response; -use App\Factory\InvoiceFactory; -use App\Filters\InvoiceFilters; -use App\Utils\Traits\MakesHash; -use App\Jobs\Invoice\ZipInvoices; -use App\Services\PdfMaker\PdfMerge; -use Illuminate\Support\Facades\App; -use App\Factory\CloneInvoiceFactory; -use App\Jobs\Invoice\BulkInvoiceJob; -use App\Utils\Traits\SavesDocuments; -use App\Jobs\Invoice\UpdateReminders; -use App\Transformers\QuoteTransformer; -use App\Repositories\InvoiceRepository; -use Illuminate\Support\Facades\Storage; -use App\Transformers\InvoiceTransformer; use App\Events\Invoice\InvoiceWasCreated; use App\Events\Invoice\InvoiceWasUpdated; +use App\Factory\CloneInvoiceFactory; use App\Factory\CloneInvoiceToQuoteFactory; +use App\Factory\InvoiceFactory; +use App\Filters\InvoiceFilters; +use App\Http\Requests\Invoice\ActionInvoiceRequest; use App\Http\Requests\Invoice\BulkInvoiceRequest; +use App\Http\Requests\Invoice\CreateInvoiceRequest; +use App\Http\Requests\Invoice\DestroyInvoiceRequest; use App\Http\Requests\Invoice\EditInvoiceRequest; use App\Http\Requests\Invoice\ShowInvoiceRequest; use App\Http\Requests\Invoice\StoreInvoiceRequest; -use App\Http\Requests\Invoice\ActionInvoiceRequest; -use App\Http\Requests\Invoice\CreateInvoiceRequest; use App\Http\Requests\Invoice\UpdateInvoiceRequest; -use App\Http\Requests\Invoice\UploadInvoiceRequest; -use App\Http\Requests\Invoice\DestroyInvoiceRequest; use App\Http\Requests\Invoice\UpdateReminderRequest; +use App\Http\Requests\Invoice\UploadInvoiceRequest; +use App\Jobs\Cron\AutoBill; +use App\Jobs\Invoice\BulkInvoiceJob; +use App\Jobs\Invoice\UpdateReminders; +use App\Jobs\Invoice\ZipInvoices; +use App\Models\Account; +use App\Models\Invoice; +use App\Models\Quote; +use App\Repositories\InvoiceRepository; +use App\Services\PdfMaker\PdfMerge; +use App\Services\Template\TemplateAction; +use App\Transformers\InvoiceTransformer; +use App\Transformers\QuoteTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Storage; /** * Class InvoiceController. @@ -504,7 +505,7 @@ class InvoiceController extends BaseController */ if ($action == 'bulk_download' && $invoices->count() > 1) { - $invoices->each(function ($invoice) use($user) { + $invoices->each(function ($invoice) use ($user) { if ($user->cannot('view', $invoice)) { nlog('access denied'); @@ -527,7 +528,7 @@ class InvoiceController extends BaseController if ($action == 'bulk_print' && $user->can('view', $invoices->first())) { $paths = $invoices->map(function ($invoice) { - return (new \App\Jobs\Entity\CreateRawPdf($invoice->invitations->first(), $invoice->company->db))->handle(); + return (new \App\Jobs\Entity\CreateRawPdf($invoice->invitations->first()))->handle(); }); $merge = (new PdfMerge($paths->toArray()))->run(); @@ -537,6 +538,24 @@ class InvoiceController extends BaseController }, 'print.pdf', ['Content-Type' => 'application/pdf']); } + if($action == 'template' && $user->can('view', $invoices->first())) { + + $hash_or_response = $request->boolean('send_email') ? 'email sent' : \Illuminate\Support\Str::uuid(); + + TemplateAction::dispatch( + $ids, + $request->template_id, + Invoice::class, + $user->id, + $user->company(), + $user->company()->db, + $hash_or_response, + $request->boolean('send_email') + ); + + return response()->json(['message' => $hash_or_response], 200); + } + /* * Send the other actions to the switch */ @@ -718,8 +737,7 @@ class InvoiceController extends BaseController return response()->json(['message' => 'email sent'], 200); } break; - - + default: return response()->json(['message' => ctrans('texts.action_unavailable', ['action' => $action])], 400); } @@ -782,7 +800,7 @@ class InvoiceController extends BaseController $file_name = $invoice->numberFormatter().'.pdf'; - $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle(); + $file = (new \App\Jobs\Entity\CreateRawPdf($invitation))->handle(); $headers = ['Content-Type' => 'application/pdf']; @@ -911,8 +929,12 @@ class InvoiceController extends BaseController $file = $invoice->service()->getInvoiceDeliveryNote($invoice, $invoice->invitations->first()->contact); return response()->streamDownload(function () use ($file) { - echo Storage::get($file); + echo $file; }, basename($file), ['Content-Type' => 'application/pdf']); + + // return response()->streamDownload(function () use ($file) { + // echo Storage::get($file); + // }, basename($file), ['Content-Type' => 'application/pdf']); } /** diff --git a/app/Http/Controllers/LicenseController.php b/app/Http/Controllers/LicenseController.php index ec130115ba..659aa77d9a 100644 --- a/app/Http/Controllers/LicenseController.php +++ b/app/Http/Controllers/LicenseController.php @@ -90,7 +90,7 @@ class LicenseController extends BaseController if(substr($license_key, 0, 3) == 'v5_') { return $this->v5ClaimLicense($license_key, $product_id); - } + } $url = config('ninja.license_url')."/claim_license?license_key={$license_key}&product_id={$product_id}&get_date=true"; $data = trim(CurlUtils::get($url)); diff --git a/app/Http/Controllers/MigrationController.php b/app/Http/Controllers/MigrationController.php index 217d29ed5e..c0bce2fe34 100644 --- a/app/Http/Controllers/MigrationController.php +++ b/app/Http/Controllers/MigrationController.php @@ -261,8 +261,9 @@ class MigrationController extends BaseController { nlog('Starting Migration'); - if($request->has('silent_migration')) + if($request->has('silent_migration')) { $this->silent_migration = true; + } if ($request->companies) { //handle Laravel 5.5 UniHTTP @@ -318,8 +319,9 @@ class MigrationController extends BaseController $nmo->settings = $user->account->companies()->first()->settings; $nmo->to_user = $user; - if(!$this->silent_migration) + if(!$this->silent_migration) { NinjaMailerJob::dispatch($nmo, true); + } return; } elseif ($existing_company && $company_count > 10) { @@ -329,8 +331,9 @@ class MigrationController extends BaseController $nmo->settings = $user->account->companies()->first()->settings; $nmo->to_user = $user; - if(!$this->silent_migration) + if(!$this->silent_migration) { NinjaMailerJob::dispatch($nmo, true); + } return; } @@ -350,8 +353,9 @@ class MigrationController extends BaseController $nmo->settings = $user->account->companies()->first(); $nmo->to_user = $user; - if(!$this->silent_migration) + if(!$this->silent_migration) { NinjaMailerJob::dispatch($nmo, true); + } return response()->json([ '_id' => Str::uuid(), diff --git a/app/Http/Controllers/OneTimeTokenController.php b/app/Http/Controllers/OneTimeTokenController.php index 70d32d42cd..6c37479b7e 100644 --- a/app/Http/Controllers/OneTimeTokenController.php +++ b/app/Http/Controllers/OneTimeTokenController.php @@ -11,15 +11,14 @@ namespace App\Http\Controllers; -use App\Models\User; -use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Support\Str; -use Illuminate\Http\Response; -use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Cache; -use App\Http\Requests\OneTimeToken\OneTimeTokenRequest; use App\Http\Requests\OneTimeToken\OneTimeRouterRequest; +use App\Http\Requests\OneTimeToken\OneTimeTokenRequest; +use App\Libraries\MultiDB; +use App\Models\Company; +use App\Models\User; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Str; class OneTimeTokenController extends BaseController { diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 413f8213ef..adc3500aca 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -14,7 +14,6 @@ namespace App\Http\Controllers; use App\Events\Payment\PaymentWasUpdated; use App\Factory\PaymentFactory; use App\Filters\PaymentFilters; -use App\Http\Requests\Payment\ActionPaymentRequest; use App\Http\Requests\Payment\CreatePaymentRequest; use App\Http\Requests\Payment\DestroyPaymentRequest; use App\Http\Requests\Payment\EditPaymentRequest; @@ -24,14 +23,12 @@ use App\Http\Requests\Payment\StorePaymentRequest; use App\Http\Requests\Payment\UpdatePaymentRequest; use App\Http\Requests\Payment\UploadPaymentRequest; use App\Models\Account; -use App\Models\Invoice; use App\Models\Payment; use App\Repositories\PaymentRepository; use App\Transformers\PaymentTransformer; use App\Utils\Ninja; use App\Utils\Traits\MakesHash; use App\Utils\Traits\SavesDocuments; -use Illuminate\Http\Request; use Illuminate\Http\Response; /** diff --git a/app/Http/Controllers/PaymentTermController.php b/app/Http/Controllers/PaymentTermController.php index a4992ca040..5c8b5ad90a 100644 --- a/app/Http/Controllers/PaymentTermController.php +++ b/app/Http/Controllers/PaymentTermController.php @@ -11,19 +11,19 @@ namespace App\Http\Controllers; -use App\Models\PaymentTerm; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; use App\Factory\PaymentTermFactory; use App\Filters\PaymentTermFilters; -use App\Repositories\PaymentTermRepository; -use App\Transformers\PaymentTermTransformer; +use App\Http\Requests\PaymentTerm\CreatePaymentTermRequest; +use App\Http\Requests\PaymentTerm\DestroyPaymentTermRequest; use App\Http\Requests\PaymentTerm\EditPaymentTermRequest; use App\Http\Requests\PaymentTerm\ShowPaymentTermRequest; use App\Http\Requests\PaymentTerm\StorePaymentTermRequest; -use App\Http\Requests\PaymentTerm\CreatePaymentTermRequest; use App\Http\Requests\PaymentTerm\UpdatePaymentTermRequest; -use App\Http\Requests\PaymentTerm\DestroyPaymentTermRequest; +use App\Models\PaymentTerm; +use App\Repositories\PaymentTermRepository; +use App\Transformers\PaymentTermTransformer; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class PaymentTermController extends BaseController { diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 6c2d217fbe..d680935af1 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -12,20 +12,15 @@ namespace App\Http\Controllers; use App\Utils\Ninja; -use App\Models\Quote; use App\Models\Client; -use App\Models\Credit; use App\Models\Invoice; use App\Utils\HtmlEngine; -use App\Libraries\MultiDB; -use App\Factory\QuoteFactory; +use Twig\Error\SyntaxError; use App\Jobs\Util\PreviewPdf; use App\Models\ClientContact; use App\Services\Pdf\PdfMock; -use App\Factory\CreditFactory; -use App\Factory\InvoiceFactory; use App\Utils\Traits\MakesHash; -use App\Models\RecurringInvoice; +use App\Services\Pdf\PdfService; use App\Utils\PhantomJS\Phantom; use App\Models\InvoiceInvitation; use App\Services\PdfMaker\Design; @@ -33,17 +28,13 @@ use App\Utils\HostedPDF\NinjaPdf; use Illuminate\Support\Facades\DB; use App\Services\PdfMaker\PdfMaker; use Illuminate\Support\Facades\App; -use App\Repositories\QuoteRepository; use Illuminate\Support\Facades\Cache; -use App\Repositories\CreditRepository; use App\Utils\Traits\MakesInvoiceHtml; use Turbo124\Beacon\Facades\LightLogs; -use App\Repositories\InvoiceRepository; use App\Utils\Traits\Pdf\PageNumbering; -use App\Factory\RecurringInvoiceFactory; use Illuminate\Support\Facades\Response; use App\DataMapper\Analytics\LivePreview; -use App\Repositories\RecurringInvoiceRepository; +use App\Services\Template\TemplateService; use App\Http\Requests\Preview\DesignPreviewRequest; use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfMakerDesign; @@ -57,24 +48,71 @@ class PreviewController extends BaseController public function __construct() { - parent::__construct(); - } - - private function purgeCache() - { - Cache::pull("preview_".auth()->user()->id); + parent::__construct(); } + public function live(PreviewInvoiceRequest $request): mixed + { + + if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) { + return response()->json(['message' => 'This server cannot handle this request.'], 400); + } + + $start = microtime(true); + + /** Build models */ + $invitation = $request->resolveInvitation(); + $client = $request->getClient(); + $settings = $client->getMergedSettings(); + $entity_prop = str_replace("recurring_", "", $request->entity); + $entity_obj = $invitation->{$request->entity}; + $entity_obj->fill($request->all()); + + if(!$entity_obj->id) { + $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"})); + $entity_obj->footer = empty($entity_obj->footer) ? $settings->{$entity_prop."_footer"} : $entity_obj->footer; + $entity_obj->terms = empty($entity_obj->terms) ? $settings->{$entity_prop."_terms"} : $entity_obj->terms; + $entity_obj->public_notes = empty($entity_obj->public_notes) ? $request->getClient()->public_notes : $entity_obj->public_notes; + $invitation->setRelation($request->entity, $entity_obj); + } + + $ps = new PdfService($invitation, 'product', [ + 'client' => $client ?? false, + // 'vendor' => $vendor ?? false, + "{$entity_prop}s" => [$entity_obj], + ]); + + $pdf = $ps->boot()->getPdf(); + + + if (Ninja::isHosted()) { + LightLogs::create(new LivePreview()) + ->increment() + ->batch(); + } + + /** Return PDF */ + return response()->streamDownload(function () use ($pdf) { + echo $pdf; + }, 'preview.pdf', [ + 'Content-Disposition' => 'inline', + 'Content-Type' => 'application/pdf', + 'Cache-Control:' => 'no-cache', + 'Server-Timing' => microtime(true)-$start + ]); + + } + /** * Refactor - 2023-10-19 - * + * * New method does not require Transactions. * * @param PreviewInvoiceRequest $request * @return mixed */ - public function live(PreviewInvoiceRequest $request): mixed - { + public function livexx(PreviewInvoiceRequest $request): mixed + { if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) { return response()->json(['message' => 'This server cannot handle this request.'], 400); @@ -101,13 +139,14 @@ class PreviewController extends BaseController if(!$entity_obj->id) { $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"})); $entity_obj->footer = empty($entity_obj->footer) ? $settings->{$entity_prop."_footer"} : $entity_obj->footer; - $entity_obj->terms = empty($entity_obj->term) ? $settings->{$entity_prop."_terms"} : $entity_obj->terms; + $entity_obj->terms = empty($entity_obj->terms) ? $settings->{$entity_prop."_terms"} : $entity_obj->terms; $entity_obj->public_notes = empty($entity_obj->public_notes) ? $request->getClient()->public_notes : $entity_obj->public_notes; $invitation->{$request->entity} = $entity_obj; } - if(empty($entity_obj->design_id)) + if(empty($entity_obj->design_id)) { $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"})); + } /** Generate variables */ $html = new HtmlEngine($invitation); @@ -116,11 +155,6 @@ class PreviewController extends BaseController $design = \App\Models\Design::query()->withTrashed()->find($entity_obj->design_id ?? 2); - /* Catch all in case migration doesn't pass back a valid design */ - if (! $design) { - $design = \App\Models\Design::query()->find(2); - } - if ($design->is_custom) { $options = [ 'custom_partials' => json_decode(json_encode($design->design), true), @@ -142,6 +176,9 @@ class PreviewController extends BaseController 'options' => [ 'all_pages_header' => $client->getSetting('all_pages_header'), 'all_pages_footer' => $client->getSetting('all_pages_footer'), + 'client' => $entity_obj->client ?? [], + 'vendor' => $entity_obj->vendor ?? [], + $request->input('entity')."s" => [$entity_obj], ], 'process_markdown' => $client->company->markdown_enabled, ]; @@ -155,8 +192,9 @@ class PreviewController extends BaseController /** Generate HTML */ $html = $maker->getCompiledHTML(true); - if (request()->query('html') == 'true') + if (request()->query('html') == 'true') { return $html; + } //if phantom js...... inject here.. if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { @@ -172,8 +210,9 @@ class PreviewController extends BaseController $pdf = (new NinjaPdf())->build($html); $numbered_pdf = $this->pageNumbering($pdf, $company); - if ($numbered_pdf) + if ($numbered_pdf) { $pdf = $numbered_pdf; + } return $pdf; } @@ -190,9 +229,9 @@ class PreviewController extends BaseController return response()->streamDownload(function () use ($pdf) { echo $pdf; }, 'preview.pdf', [ - 'Content-Disposition' => 'inline', - 'Content-Type' => 'application/pdf', - 'Cache-Control:' => 'no-cache', + 'Content-Disposition' => 'inline', + 'Content-Type' => 'application/pdf', + 'Cache-Control:' => 'no-cache', 'Server-Timing' => microtime(true)-$start ]); @@ -203,7 +242,7 @@ class PreviewController extends BaseController * Returns the mocked PDF for the invoice design preview. * * Only used in Settings > Invoice Design as a general overview - * + * * @param DesignPreviewRequest $request * @return mixed */ @@ -228,12 +267,16 @@ class PreviewController extends BaseController /** * Returns a template filled with entity variables. - * + * * Used in the Custom Designer to preview design changes * @return mixed */ public function show() { + if(request()->has('template')) { + return $this->template(); + } + if (request()->has('entity') && request()->has('entity_id') && ! empty(request()->input('entity')) && @@ -278,6 +321,11 @@ class PreviewController extends BaseController ]), 'variables' => $html->generateLabelsAndValues(), 'process_markdown' => $entity_obj->client->company->markdown_enabled, + 'options' => [ + 'client' => $entity_obj->client ?? [], + 'vendor' => $entity_obj->vendor ?? [], + request()->input('entity_type', 'invoice')."s" => [$entity_obj], + ] ]; $design = new Design(request()->design['name']); @@ -304,8 +352,9 @@ class PreviewController extends BaseController $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); $numbered_pdf = $this->pageNumbering($pdf, $company); - if ($numbered_pdf) + if ($numbered_pdf) { $pdf = $numbered_pdf; + } return $pdf; @@ -327,191 +376,62 @@ class PreviewController extends BaseController return $this->blankEntity(); } - - - /** - * @deprecated due to usage of transactions - * - * @param PreviewInvoiceRequest $request - * @return mixed - */ - public function livex(PreviewInvoiceRequest $request) + private function template() { - if(Cache::has("preview_".auth()->user()->id)) - return response()->json(['message' => 'Please wait a few seconds before trying again, this many requests are not good.'], 400); - - if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) { - return response()->json(['message' => 'This server cannot handle this request.'], 400); - } - - Cache::put("preview_".auth()->user()->id, 60); - - $start = microtime(true); - /** @var \App\Models\User $user */ $user = auth()->user(); + /** @var \App\Models\Company $company */ $company = $user->company(); - MultiDB::setDb($company->db); - - if ($request->input('entity') == 'quote') { - $repo = new QuoteRepository(); - $entity_obj = QuoteFactory::create($company->id, $user->id); - $class = Quote::class; - } elseif ($request->input('entity') == 'credit') { - $repo = new CreditRepository(); - $entity_obj = CreditFactory::create($company->id, $user->id); - $class = Credit::class; - } elseif ($request->input('entity') == 'recurring_invoice') { - $repo = new RecurringInvoiceRepository(); - $entity_obj = RecurringInvoiceFactory::create($company->id, $user->id); - $class = RecurringInvoice::class; - } else { //assume it is either an invoice or a null object - $repo = new InvoiceRepository(); - $entity_obj = InvoiceFactory::create($company->id, $user->id); - $class = Invoice::class; - } + $design_object = json_decode(json_encode(request()->input('design')), 1); + $ts = (new TemplateService()); try { - DB::connection(config('database.default'))->beginTransaction(); + $ts->setCompany($company) + ->setTemplate($design_object) + ->mock(); + } catch(SyntaxError $e) { - if ($request->has('entity_id')) { + // return response()->json(['message' => 'Twig syntax is invalid.', 'errors' => new \stdClass], 422); - /** @var \App\Models\Quote | \App\Models\Invoice | \App\Models\RecurringInvoice | \App\Models\Credit $class */ - $temp_obj = $class::on(config('database.default')) - ->with('client.company') - ->where('id', $this->decodePrimaryKey($request->input('entity_id'))) - ->where('company_id', $company->id) - ->withTrashed() - ->first(); - - /** Prevents null values from being passed into entity_obj */ - if($temp_obj) - $entity_obj = $temp_obj; - } - - if ($request->has('footer') && !$request->filled('footer') && $request->input('entity') == 'recurring_invoice') { - $request->merge(['footer' => $company->settings->invoice_footer]); - } - - if ($request->has('terms') && !$request->filled('terms') && $request->input('entity') == 'recurring_invoice') { - $request->merge(['terms' => $company->settings->invoice_terms]); - } - - $entity_obj = $repo->save($request->all(), $entity_obj); - - if (! $request->has('entity_id')) { - $entity_obj->service()->fillDefaults()->save(); - } - - App::forgetInstance('translator'); - $t = app('translator'); - App::setLocale($entity_obj->client->locale()); - $t->replace(Ninja::transformTranslations($entity_obj->client->getMergedSettings())); - - $html = new HtmlEngine($entity_obj->invitations()->first()); - - /** @var \App\Models\Design $design */ - $design = \App\Models\Design::withTrashed()->find($entity_obj->design_id); - - /* Catch all in case migration doesn't pass back a valid design */ - if (! $design) { - $design = \App\Models\Design::find(2); - } - - if ($design->is_custom) { - $options = [ - 'custom_partials' => json_decode(json_encode($design->design), true), - ]; - $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); - } else { - $template = new PdfMakerDesign(strtolower($design->name)); - } - - $variables = $html->generateLabelsAndValues(); - - $state = [ - 'template' => $template->elements([ - 'client' => $entity_obj->client, - 'entity' => $entity_obj, - 'pdf_variables' => (array) $entity_obj->company->settings->pdf_variables, - '$product' => $design->design->product, - 'variables' => $variables, - ]), - 'variables' => $variables, - 'options' => [ - 'all_pages_header' => $entity_obj->client->getSetting('all_pages_header'), - 'all_pages_footer' => $entity_obj->client->getSetting('all_pages_footer'), - ], - 'process_markdown' => $entity_obj->client->company->markdown_enabled, - ]; - - $maker = new PdfMaker($state); - - $maker - ->design($template) - ->build(); - - DB::connection(config('database.default'))->rollBack(); - - if (request()->query('html') == 'true') { - $this->purgeCache(); - return $maker->getCompiledHTML(); - } - - } catch(\Exception $e) { - - $this->purgeCache(); - - DB::connection(config('database.default'))->rollBack(); - - if (DB::connection(config('database.default'))->transactionLevel() > 0) { - DB::connection(config('database.default'))->rollBack(); - } - - return response()->json(['message' => 'Error generating preview. Please retry again shortly.'], 400); } - //if phantom js...... inject here.. - if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { - $this->purgeCache(); - return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); - } - - /** @var \App\Models\User $user */ - $user = auth()->user(); + $html = $ts->getHtml(); - /** @var \App\Models\Company $company */ - $company = $user->company(); - - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { - $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); - - $numbered_pdf = $this->pageNumbering($pdf, $company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - $this->purgeCache(); - return $pdf; - } - - $file_path = (new PreviewPdf($maker->getCompiledHTML(true), $company))->handle(); - - if (Ninja::isHosted()) { - LightLogs::create(new LivePreview()) - ->increment() - ->batch(); + if (request()->query('html') == 'true') { + return $html; } + if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { + return (new Phantom)->convertHtmlToPdf($html); + } + + if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { + $pdf = (new NinjaPdf())->build($html); + + $numbered_pdf = $this->pageNumbering($pdf, $company); + + if ($numbered_pdf) { + $pdf = $numbered_pdf; + } + + return $pdf; + } + + $file_path = (new PreviewPdf($html, $company))->handle(); + $response = Response::make($file_path, 200); $response->header('Content-Type', 'application/pdf'); - $response->header('Server-Timing', microtime(true)-$start); - $this->purgeCache(); return $response; + + } + + private function stubTemplateData() + { + } private function blankEntity() @@ -554,6 +474,10 @@ class PreviewController extends BaseController ]), 'variables' => $html->generateLabelsAndValues(), 'process_markdown' => $invitation->invoice->client->company->markdown_enabled, + 'options' => [ + 'client' => $invitation->invoice->client, + 'invoices' => [$invitation->invoice], + ] ]; $maker = new PdfMaker($state); @@ -604,76 +528,84 @@ class PreviewController extends BaseController /** @var \App\Models\Company $company */ $company = $user->company(); + try { + DB::connection($company->db)->beginTransaction(); - DB::connection($company->db)->beginTransaction(); + /** @var \App\Models\Client $client */ + $client = Client::factory()->create([ + 'user_id' => auth()->user()->id, + 'company_id' => $company->id, + ]); - /** @var \App\Models\Client $client */ - $client = Client::factory()->create([ - 'user_id' => auth()->user()->id, - 'company_id' => $company->id, - ]); + /** @var \App\Models\ClientContact $contact */ + $contact = ClientContact::factory()->create([ + 'user_id' => auth()->user()->id, + 'company_id' => $company->id, + 'client_id' => $client->id, + 'is_primary' => 1, + 'send_email' => true, + ]); - /** @var \App\Models\ClientContact $contact */ - $contact = ClientContact::factory()->create([ - 'user_id' => auth()->user()->id, - 'company_id' => $company->id, - 'client_id' => $client->id, - 'is_primary' => 1, - 'send_email' => true, - ]); + /** @var \App\Models\Invoice $invoice */ - /** @var \App\Models\Invoice $invoice */ + $invoice = Invoice::factory()->create([ + 'user_id' => auth()->user()->id, + 'company_id' => $company->id, + 'client_id' => $client->id, + 'terms' => $company->settings->invoice_terms, + 'footer' => $company->settings->invoice_footer, + 'public_notes' => 'Sample Public Notes', + ]); - $invoice = Invoice::factory()->create([ - 'user_id' => auth()->user()->id, - 'company_id' => $company->id, - 'client_id' => $client->id, - 'terms' => $company->settings->invoice_terms, - 'footer' => $company->settings->invoice_footer, - 'public_notes' => 'Sample Public Notes', - ]); + $invitation = InvoiceInvitation::factory()->create([ + 'user_id' => auth()->user()->id, + 'company_id' => $company->id, + 'invoice_id' => $invoice->id, + 'client_contact_id' => $contact->id, + ]); - $invitation = InvoiceInvitation::factory()->create([ - 'user_id' => auth()->user()->id, - 'company_id' => $company->id, - 'invoice_id' => $invoice->id, - 'client_contact_id' => $contact->id, - ]); + $invoice->setRelation('invitations', $invitation); + $invoice->setRelation('client', $client); + $invoice->setRelation('company', $company); + $invoice->load('client.company'); - $invoice->setRelation('invitations', $invitation); - $invoice->setRelation('client', $client); - $invoice->setRelation('company', $company); - $invoice->load('client.company'); + $design_object = json_decode(json_encode(request()->input('design'))); - $design_object = json_decode(json_encode(request()->input('design'))); + if (! is_object($design_object)) { + return response()->json(['message' => 'Invalid custom design object'], 400); + } - if (! is_object($design_object)) { - return response()->json(['message' => 'Invalid custom design object'], 400); + $html = new HtmlEngine($invoice->invitations()->first()); + + $design = new Design(Design::CUSTOM, ['custom_partials' => request()->design['design']]); + + $state = [ + 'template' => $design->elements([ + 'client' => $invoice->client, + 'entity' => $invoice, + 'pdf_variables' => (array) $invoice->company->settings->pdf_variables, + 'products' => request()->design['design']['product'], + ]), + 'variables' => $html->generateLabelsAndValues(), + 'process_markdown' => $invoice->client->company->markdown_enabled, + 'options' => [ + 'client' => $invoice->client, + 'invoices' => [$invoice], + ] + ]; + + $maker = new PdfMaker($state); + + $maker + ->design($design) + ->build(); + + DB::connection($company->db)->rollBack(); + } catch(\Exception $e) { + DB::connection($company->db)->rollBack(); + return response()->json(['message' => $e->getMessage()], 400); } - $html = new HtmlEngine($invoice->invitations()->first()); - - $design = new Design(Design::CUSTOM, ['custom_partials' => request()->design['design']]); - - $state = [ - 'template' => $design->elements([ - 'client' => $invoice->client, - 'entity' => $invoice, - 'pdf_variables' => (array) $invoice->company->settings->pdf_variables, - 'products' => request()->design['design']['product'], - ]), - 'variables' => $html->generateLabelsAndValues(), - 'process_markdown' => $invoice->client->company->markdown_enabled, - ]; - - $maker = new PdfMaker($state); - - $maker - ->design($design) - ->build(); - - DB::connection($company->db)->rollBack(); - if (request()->query('html') == 'true') { return $maker->getCompiledHTML(); } diff --git a/app/Http/Controllers/PreviewPurchaseOrderController.php b/app/Http/Controllers/PreviewPurchaseOrderController.php index 81d823cf25..5884e09f56 100644 --- a/app/Http/Controllers/PreviewPurchaseOrderController.php +++ b/app/Http/Controllers/PreviewPurchaseOrderController.php @@ -11,32 +11,33 @@ namespace App\Http\Controllers; -use App\DataMapper\Analytics\LivePreview; -use App\Factory\PurchaseOrderFactory; -use App\Http\Requests\Preview\PreviewPurchaseOrderRequest; -use App\Jobs\Util\PreviewPdf; -use App\Libraries\MultiDB; +use App\Utils\Ninja; use App\Models\Client; -use App\Models\PurchaseOrder; -use App\Models\PurchaseOrderInvitation; use App\Models\Vendor; +use App\Libraries\MultiDB; +use App\Jobs\Util\PreviewPdf; +use App\Models\PurchaseOrder; use App\Models\VendorContact; -use App\Repositories\PurchaseOrderRepository; +use App\Utils\Traits\MakesHash; +use App\Utils\VendorHtmlEngine; +use App\Services\Pdf\PdfService; +use App\Utils\PhantomJS\Phantom; use App\Services\PdfMaker\Design; +use App\Utils\HostedPDF\NinjaPdf; +use Illuminate\Support\Facades\DB; +use App\Services\PdfMaker\PdfMaker; +use Illuminate\Support\Facades\App; +use App\Factory\PurchaseOrderFactory; +use App\Utils\Traits\MakesInvoiceHtml; +use Turbo124\Beacon\Facades\LightLogs; +use App\Models\PurchaseOrderInvitation; +use App\Utils\Traits\Pdf\PageNumbering; +use Illuminate\Support\Facades\Response; +use App\DataMapper\Analytics\LivePreview; +use App\Repositories\PurchaseOrderRepository; use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfMakerDesign; -use App\Services\PdfMaker\PdfMaker; -use App\Utils\HostedPDF\NinjaPdf; -use App\Utils\Ninja; -use App\Utils\PhantomJS\Phantom; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\MakesInvoiceHtml; -use App\Utils\Traits\Pdf\PageNumbering; -use App\Utils\VendorHtmlEngine; -use Illuminate\Support\Facades\App; -use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Response; -use Turbo124\Beacon\Facades\LightLogs; +use App\Http\Requests\Preview\PreviewPurchaseOrderRequest; class PreviewPurchaseOrderController extends BaseController { @@ -122,6 +123,10 @@ class PreviewPurchaseOrderController extends BaseController ]), 'variables' => $html->generateLabelsAndValues(), 'process_markdown' => $entity_obj->company->markdown_enabled, + 'options' => [ + 'vendor' => $entity_obj->vendor ?? [], + request()->input('entity')."s" => [$entity_obj], + ] ]; $design = new Design(request()->design['name']); @@ -165,6 +170,56 @@ class PreviewPurchaseOrderController extends BaseController } public function live(PreviewPurchaseOrderRequest $request) + { + + $start = microtime(true); + + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $invitation = $request->resolveInvitation(); + $vendor = $request->getVendor(); + $settings = $user->company()->settings; + $entity_obj = $invitation->purchase_order; + $entity_obj->fill($request->all()); + + if(!$entity_obj->id) { + $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{"purchase_order_design_id"})); + $entity_obj->footer = empty($entity_obj->footer) ? $settings->{"purchase_order_footer"} : $entity_obj->footer; + $entity_obj->terms = empty($entity_obj->terms) ? $settings->{"purchase_order_terms"} : $entity_obj->terms; + $entity_obj->public_notes = empty($entity_obj->public_notes) ? $request->getVendor()->public_notes : $entity_obj->public_notes; + $invitation->setRelation($request->entity, $entity_obj); + + } + + $ps = new PdfService($invitation, 'purchase_order', [ + 'client' => $entity_obj->client ?? false, + 'vendor' => $vendor ?? false, + "purchase_orders" => [$entity_obj], + ]); + + $pdf = $ps->boot()->getPdf(); + + if (Ninja::isHosted()) { + LightLogs::create(new LivePreview()) + ->increment() + ->batch(); + } + + /** Return PDF */ + return response()->streamDownload(function () use ($pdf) { + echo $pdf; + }, 'preview.pdf', [ + 'Content-Disposition' => 'inline', + 'Content-Type' => 'application/pdf', + 'Cache-Control:' => 'no-cache', + 'Server-Timing' => microtime(true)-$start + ]); + + + } + + public function livex(PreviewPurchaseOrderRequest $request) { /** @var \App\Models\User $user */ $user = auth()->user(); @@ -232,6 +287,12 @@ class PreviewPurchaseOrderController extends BaseController '$product' => $design->design->product, ]), 'variables' => $html->generateLabelsAndValues(), + 'options' => [ + 'client' => null, + 'vendor' => $entity_obj->vendor, + 'purchase_orders' => [$entity_obj], + 'variables' => $html->generateLabelsAndValues(), + ], 'process_markdown' => $entity_obj->company->markdown_enabled, ]; @@ -254,24 +315,24 @@ class PreviewPurchaseOrderController extends BaseController /** @var \App\Models\User $user */ $user = auth()->user(); - //if phantom js...... inject here.. - if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { - return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); - } + //if phantom js...... inject here.. + if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { + return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); + } - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { - $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); + if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { + $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); - $numbered_pdf = $this->pageNumbering($pdf, $user->company()); + $numbered_pdf = $this->pageNumbering($pdf, $user->company()); - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - - return $pdf; + if ($numbered_pdf) { + $pdf = $numbered_pdf; } - $file_path = (new PreviewPdf($maker->getCompiledHTML(true), $company))->handle(); + return $pdf; + } + + $file_path = (new PreviewPdf($maker->getCompiledHTML(true), $company))->handle(); if (Ninja::isHosted()) { @@ -324,6 +385,10 @@ class PreviewPurchaseOrderController extends BaseController ]), 'variables' => $html->generateLabelsAndValues(), 'process_markdown' => $invitation->company->markdown_enabled, + 'options' => [ + 'vendor' => $invitation->purchase_order->vendor, + 'purchase_orders' => [$invitation->purchase_order], + ], ]; @@ -429,6 +494,10 @@ class PreviewPurchaseOrderController extends BaseController ]), 'variables' => $html->generateLabelsAndValues(), 'process_markdown' => $purchase_order->company->markdown_enabled, + 'options' => [ + 'vendor' => $invitation->purchase_order->vendor, + 'purchase_orders' => [$invitation->purchase_order], + ], ]; $maker = new PdfMaker($state); diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index cc2784f5c0..c6bf1acc36 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -467,7 +467,7 @@ class ProductController extends BaseController $products = Product::withTrashed()->whereIn('id', $ids); - if($action == 'set_tax_id'){ + if($action == 'set_tax_id') { $tax_id = $request->input('tax_id'); diff --git a/app/Http/Controllers/ProtectedDownloadController.php b/app/Http/Controllers/ProtectedDownloadController.php index 014527bace..51c9077419 100644 --- a/app/Http/Controllers/ProtectedDownloadController.php +++ b/app/Http/Controllers/ProtectedDownloadController.php @@ -11,10 +11,8 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use Illuminate\Http\Request; -use App\Jobs\Util\UnlinkFile; use App\Exceptions\SystemError; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Storage; diff --git a/app/Http/Controllers/PurchaseOrderController.php b/app/Http/Controllers/PurchaseOrderController.php index 4ed383f308..4b0ad2e006 100644 --- a/app/Http/Controllers/PurchaseOrderController.php +++ b/app/Http/Controllers/PurchaseOrderController.php @@ -11,33 +11,33 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Client; -use App\Models\Account; -use App\Models\PurchaseOrder; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Services\PdfMaker\PdfMerge; -use Illuminate\Support\Facades\App; -use App\Utils\Traits\SavesDocuments; -use App\Factory\PurchaseOrderFactory; -use App\Filters\PurchaseOrderFilters; -use Illuminate\Support\Facades\Storage; -use App\Jobs\PurchaseOrder\ZipPurchaseOrders; -use App\Repositories\PurchaseOrderRepository; -use App\Jobs\PurchaseOrder\PurchaseOrderEmail; -use App\Transformers\PurchaseOrderTransformer; use App\Events\PurchaseOrder\PurchaseOrderWasCreated; use App\Events\PurchaseOrder\PurchaseOrderWasUpdated; +use App\Factory\PurchaseOrderFactory; +use App\Filters\PurchaseOrderFilters; +use App\Http\Requests\PurchaseOrder\ActionPurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\BulkPurchaseOrderRequest; +use App\Http\Requests\PurchaseOrder\CreatePurchaseOrderRequest; +use App\Http\Requests\PurchaseOrder\DestroyPurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\EditPurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\ShowPurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\StorePurchaseOrderRequest; -use App\Http\Requests\PurchaseOrder\ActionPurchaseOrderRequest; -use App\Http\Requests\PurchaseOrder\CreatePurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\UpdatePurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\UploadPurchaseOrderRequest; -use App\Http\Requests\PurchaseOrder\DestroyPurchaseOrderRequest; +use App\Jobs\Entity\CreateRawPdf; +use App\Jobs\PurchaseOrder\PurchaseOrderEmail; +use App\Jobs\PurchaseOrder\ZipPurchaseOrders; +use App\Models\Account; +use App\Models\Client; +use App\Models\PurchaseOrder; +use App\Repositories\PurchaseOrderRepository; +use App\Services\PdfMaker\PdfMerge; +use App\Transformers\PurchaseOrderTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\Storage; class PurchaseOrderController extends BaseController { @@ -367,7 +367,6 @@ class PurchaseOrderController extends BaseController $purchase_order = $purchase_order->service() ->triggeredActions($request) - // ->touchPdf() ->save(); event(new PurchaseOrderWasUpdated($purchase_order, $purchase_order->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); @@ -502,7 +501,7 @@ class PurchaseOrderController extends BaseController * Download Purchase Order/s */ if ($action == 'bulk_download' && $purchase_orders->count() >= 1) { - $purchase_orders->each(function ($purchase_order) use ($user){ + $purchase_orders->each(function ($purchase_order) use ($user) { if ($user->cannot('view', $purchase_order)) { return response()->json(['message' => ctrans('text.access_denied')]); } @@ -515,7 +514,7 @@ class PurchaseOrderController extends BaseController if ($action == 'bulk_print' && $user->can('view', $purchase_orders->first())) { $paths = $purchase_orders->map(function ($purchase_order) { - return (new \App\Jobs\Vendor\CreatePurchaseOrderPdf($purchase_order->invitations->first()))->rawPdf(); + return (new CreateRawPdf($purchase_order->invitations->first()))->handle(); }); $merge = (new PdfMerge($paths->toArray()))->run(); @@ -624,8 +623,8 @@ class PurchaseOrderController extends BaseController $file = $purchase_order->service()->getPurchaseOrderPdf(); return response()->streamDownload(function () use ($file) { - echo Storage::get($file); - }, basename($file), ['Content-Type' => 'application/pdf']); + echo $file; + }, $purchase_order->numberFormatter().".pdf", ['Content-Type' => 'application/pdf']); break; case 'restore': @@ -829,7 +828,7 @@ class PurchaseOrderController extends BaseController } return response()->streamDownload(function () use ($file) { - echo Storage::get($file); - }, basename($file), $headers); + echo $file; + }, $purchase_order->numberFormatter().".pdf", $headers); } } diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index 45cfc2293f..94f3218d73 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -11,41 +11,40 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Quote; -use App\Models\Client; -use App\Models\Account; -use App\Models\Invoice; -use App\Models\Project; -use Illuminate\Http\Request; -use App\Factory\QuoteFactory; -use App\Filters\QuoteFilters; -use App\Jobs\Quote\ZipQuotes; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Factory\CloneQuoteFactory; -use App\Services\PdfMaker\PdfMerge; -use Illuminate\Support\Facades\App; -use App\Utils\Traits\SavesDocuments; use App\Events\Quote\QuoteWasCreated; use App\Events\Quote\QuoteWasUpdated; -use App\Repositories\QuoteRepository; -use App\Transformers\QuoteTransformer; -use App\Utils\Traits\GeneratesCounter; -use Illuminate\Support\Facades\Storage; -use App\Transformers\InvoiceTransformer; -use App\Transformers\ProjectTransformer; +use App\Factory\CloneQuoteFactory; use App\Factory\CloneQuoteToInvoiceFactory; -use App\Factory\CloneQuoteToProjectFactory; +use App\Factory\QuoteFactory; +use App\Filters\QuoteFilters; +use App\Http\Requests\Quote\ActionQuoteRequest; +use App\Http\Requests\Quote\BulkActionQuoteRequest; +use App\Http\Requests\Quote\CreateQuoteRequest; +use App\Http\Requests\Quote\DestroyQuoteRequest; use App\Http\Requests\Quote\EditQuoteRequest; use App\Http\Requests\Quote\ShowQuoteRequest; use App\Http\Requests\Quote\StoreQuoteRequest; -use App\Http\Requests\Quote\ActionQuoteRequest; -use App\Http\Requests\Quote\CreateQuoteRequest; use App\Http\Requests\Quote\UpdateQuoteRequest; use App\Http\Requests\Quote\UploadQuoteRequest; -use App\Http\Requests\Quote\DestroyQuoteRequest; -use App\Http\Requests\Quote\BulkActionQuoteRequest; +use App\Jobs\Quote\ZipQuotes; +use App\Models\Account; +use App\Models\Client; +use App\Models\Invoice; +use App\Models\Project; +use App\Models\Quote; +use App\Repositories\QuoteRepository; +use App\Services\PdfMaker\PdfMerge; +use App\Transformers\InvoiceTransformer; +use App\Transformers\ProjectTransformer; +use App\Transformers\QuoteTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\GeneratesCounter; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use Illuminate\Http\Request; +use Illuminate\Http\Response; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Storage; /** * Class QuoteController. @@ -398,7 +397,7 @@ class QuoteController extends BaseController $quote->service() ->triggeredActions($request); - // ->deletePdf(); + // ->deletePdf(); event(new QuoteWasUpdated($quote, $quote->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); @@ -536,7 +535,7 @@ class QuoteController extends BaseController * Download Quote/s */ if ($action == 'bulk_download' && $quotes->count() >= 1) { - $quotes->each(function ($quote) use($user){ + $quotes->each(function ($quote) use ($user) { if ($user->cannot('view', $quote)) { return response()->json(['message'=> ctrans('texts.access_denied')]); } @@ -562,7 +561,7 @@ class QuoteController extends BaseController if ($action == 'bulk_print' && $user->can('view', $quotes->first())) { $paths = $quotes->map(function ($quote) { - return (new \App\Jobs\Entity\CreateRawPdf($quote->invitations->first(), $quote->company->db))->handle(); + return (new \App\Jobs\Entity\CreateRawPdf($quote->invitations->first()))->handle(); }); $merge = (new PdfMerge($paths->toArray()))->run(); @@ -687,7 +686,7 @@ class QuoteController extends BaseController return $this->itemResponse($quote->service()->convertToProject()); - case 'convert': + case 'convert': case 'convert_to_invoice': $this->entity_type = Invoice::class; @@ -724,8 +723,8 @@ class QuoteController extends BaseController $file = $quote->service()->getQuotePdf(); return response()->streamDownload(function () use ($file) { - echo Storage::get($file); - }, basename($file), ['Content-Type' => 'application/pdf']); + echo $file; + }, $quote->numberFormatter().".pdf", ['Content-Type' => 'application/pdf']); case 'restore': $this->quote_repo->restore($quote); @@ -828,17 +827,18 @@ class QuoteController extends BaseController App::setLocale($invitation->contact->preferredLocale()); - $file = $quote->service()->getQuotePdf($contact); - $headers = ['Content-Type' => 'application/pdf']; if (request()->input('inline') == 'true') { $headers = array_merge($headers, ['Content-Disposition' => 'inline']); } + $file = $quote->service()->getQuotePdf($contact); + return response()->streamDownload(function () use ($file) { - echo Storage::get($file); - }, basename($file), $headers); + echo $file; + }, $quote->numberFormatter().".pdf", $headers); + } /** diff --git a/app/Http/Controllers/RecurringInvoiceController.php b/app/Http/Controllers/RecurringInvoiceController.php index 94c2192d17..aae571d71d 100644 --- a/app/Http/Controllers/RecurringInvoiceController.php +++ b/app/Http/Controllers/RecurringInvoiceController.php @@ -11,28 +11,28 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; -use App\Models\Account; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Models\RecurringInvoice; -use App\Utils\Traits\SavesDocuments; -use App\Factory\RecurringInvoiceFactory; -use App\Filters\RecurringInvoiceFilters; -use App\Jobs\RecurringInvoice\UpdateRecurring; -use App\Repositories\RecurringInvoiceRepository; -use App\Transformers\RecurringInvoiceTransformer; use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; use App\Events\RecurringInvoice\RecurringInvoiceWasUpdated; +use App\Factory\RecurringInvoiceFactory; +use App\Filters\RecurringInvoiceFilters; +use App\Http\Requests\RecurringInvoice\ActionRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\BulkRecurringInvoiceRequest; +use App\Http\Requests\RecurringInvoice\CreateRecurringInvoiceRequest; +use App\Http\Requests\RecurringInvoice\DestroyRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\EditRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\ShowRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\StoreRecurringInvoiceRequest; -use App\Http\Requests\RecurringInvoice\ActionRecurringInvoiceRequest; -use App\Http\Requests\RecurringInvoice\CreateRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\UpdateRecurringInvoiceRequest; use App\Http\Requests\RecurringInvoice\UploadRecurringInvoiceRequest; -use App\Http\Requests\RecurringInvoice\DestroyRecurringInvoiceRequest; +use App\Jobs\RecurringInvoice\UpdateRecurring; +use App\Models\Account; +use App\Models\RecurringInvoice; +use App\Repositories\RecurringInvoiceRepository; +use App\Transformers\RecurringInvoiceTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; +use Illuminate\Http\Response; /** * Class RecurringInvoiceController. @@ -580,7 +580,7 @@ class RecurringInvoiceController extends BaseController $file_name = $invoice->numberFormatter().'.pdf'; - $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle(); + $file = (new \App\Jobs\Entity\CreateRawPdf($invitation))->handle(); $headers = ['Content-Type' => 'application/pdf']; diff --git a/app/Http/Controllers/RecurringQuoteController.php b/app/Http/Controllers/RecurringQuoteController.php index 348440c234..725980110a 100644 --- a/app/Http/Controllers/RecurringQuoteController.php +++ b/app/Http/Controllers/RecurringQuoteController.php @@ -578,8 +578,8 @@ class RecurringQuoteController extends BaseController { switch ($action) { case 'clone_to_recurring_quote': - // $recurring_invoice = CloneRecurringQuoteFactory::create($recurring_invoice, auth()->user()->id); - // return $this->itemResponse($recurring_invoice); + // $recurring_invoice = CloneRecurringQuoteFactory::create($recurring_invoice, auth()->user()->id); + // return $this->itemResponse($recurring_invoice); break; case 'clone_to_quote': // $quote = CloneRecurringQuoteToQuoteFactory::create($recurring_invoice, auth()->user()->id); diff --git a/app/Http/Controllers/Reports/ARDetailReportController.php b/app/Http/Controllers/Reports/ARDetailReportController.php index 4f6c460e7a..1d37848222 100644 --- a/app/Http/Controllers/Reports/ARDetailReportController.php +++ b/app/Http/Controllers/Reports/ARDetailReportController.php @@ -11,11 +11,11 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Services\Report\ARDetailReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\SendToAdmin; +use App\Services\Report\ARDetailReport; +use App\Utils\Traits\MakesHash; class ARDetailReportController extends BaseController { diff --git a/app/Http/Controllers/Reports/ARSummaryReportController.php b/app/Http/Controllers/Reports/ARSummaryReportController.php index a9c9f6e689..cde4779451 100644 --- a/app/Http/Controllers/Reports/ARSummaryReportController.php +++ b/app/Http/Controllers/Reports/ARSummaryReportController.php @@ -61,14 +61,17 @@ class ARSummaryReportController extends BaseController */ public function __invoke(GenericReportRequest $request) { + /** @var \App\Models\User $user */ + $user = auth()->user(); + if ($request->has('send_email') && $request->get('send_email')) { - SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ARSummaryReport::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), ARSummaryReport::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // expect a list of visible fields, or use the default - $export = new ARSummaryReport(auth()->user()->company(), $request->all()); + $export = new ARSummaryReport($user->company(), $request->all()); $csv = $export->run(); diff --git a/app/Http/Controllers/Reports/ActivityReportController.php b/app/Http/Controllers/Reports/ActivityReportController.php index ed241a9e38..f9af9fa3af 100644 --- a/app/Http/Controllers/Reports/ActivityReportController.php +++ b/app/Http/Controllers/Reports/ActivityReportController.php @@ -11,12 +11,12 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Export\CSV\ActivityExport; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; class ActivityReportController extends BaseController { @@ -41,28 +41,12 @@ class ActivityReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), ActivityExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), ActivityExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new ActivityExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ClientBalanceReportController.php b/app/Http/Controllers/Reports/ClientBalanceReportController.php index 0202af3d2f..c29b0a213a 100644 --- a/app/Http/Controllers/Reports/ClientBalanceReportController.php +++ b/app/Http/Controllers/Reports/ClientBalanceReportController.php @@ -11,12 +11,11 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Http\Controllers\BaseController; -use App\Services\Report\ARSummaryReport; -use App\Services\Report\ClientBalanceReport; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\SendToAdmin; +use App\Services\Report\ClientBalanceReport; +use App\Utils\Traits\MakesHash; class ClientBalanceReportController extends BaseController { diff --git a/app/Http/Controllers/Reports/ClientContactReportController.php b/app/Http/Controllers/Reports/ClientContactReportController.php index e29eefe195..0062eeffa9 100644 --- a/app/Http/Controllers/Reports/ClientContactReportController.php +++ b/app/Http/Controllers/Reports/ClientContactReportController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Export\CSV\ContactExport; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class ClientContactReportController extends BaseController { @@ -72,30 +72,11 @@ class ClientContactReportController extends BaseController return response()->json(['message' => 'working...'], 200); } + $hash = \Illuminate\Support\Str::uuid(); - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + PreviewReport::dispatch($user->company(), $request->all(), ContactExport::class, $hash); - $hash = \Illuminate\Support\Str::uuid(); + return response()->json(['message' => $hash], 200); - PreviewReport::dispatch($user->company(), $request->all(), ContactExport::class, $hash); - - return response()->json(['message' => $hash], 200); - } - - - // expect a list of visible fields, or use the default - $export = new ContactExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ClientReportController.php b/app/Http/Controllers/Reports/ClientReportController.php index bcbc2c02d9..a0ff126cc6 100644 --- a/app/Http/Controllers/Reports/ClientReportController.php +++ b/app/Http/Controllers/Reports/ClientReportController.php @@ -11,14 +11,14 @@ namespace App\Http\Controllers\Reports; -use App\Models\Client; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; use App\Export\CSV\ClientExport; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Models\Client; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class ClientReportController extends BaseController { @@ -73,27 +73,11 @@ class ClientReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), ClientExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), ClientExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new ClientExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ClientSalesReportController.php b/app/Http/Controllers/Reports/ClientSalesReportController.php index 056b157775..63c0ac69fe 100644 --- a/app/Http/Controllers/Reports/ClientSalesReportController.php +++ b/app/Http/Controllers/Reports/ClientSalesReportController.php @@ -11,12 +11,11 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Http\Controllers\BaseController; -use App\Services\Report\ClientSalesReport; -use App\Services\Report\ClientBalanceReport; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\SendToAdmin; +use App\Services\Report\ClientSalesReport; +use App\Utils\Traits\MakesHash; class ClientSalesReportController extends BaseController { diff --git a/app/Http/Controllers/Reports/CreditReportController.php b/app/Http/Controllers/Reports/CreditReportController.php index 5a1a952d63..533a45e046 100644 --- a/app/Http/Controllers/Reports/CreditReportController.php +++ b/app/Http/Controllers/Reports/CreditReportController.php @@ -71,28 +71,12 @@ class CreditReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), CreditExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), CreditExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new CreditExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/DocumentReportController.php b/app/Http/Controllers/Reports/DocumentReportController.php index d0cd939c86..fb592f9909 100644 --- a/app/Http/Controllers/Reports/DocumentReportController.php +++ b/app/Http/Controllers/Reports/DocumentReportController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Export\CSV\DocumentExport; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class DocumentReportController extends BaseController { @@ -72,28 +72,12 @@ class DocumentReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), DocumentExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), DocumentExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new DocumentExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ExpenseReportController.php b/app/Http/Controllers/Reports/ExpenseReportController.php index f1276cdaff..12e3c7cf81 100644 --- a/app/Http/Controllers/Reports/ExpenseReportController.php +++ b/app/Http/Controllers/Reports/ExpenseReportController.php @@ -11,14 +11,14 @@ namespace App\Http\Controllers\Reports; -use App\Models\Client; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Export\CSV\ExpenseExport; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Models\Client; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class ExpenseReportController extends BaseController { @@ -73,28 +73,12 @@ class ExpenseReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), ExpenseExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), ExpenseExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new ExpenseExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/InvoiceItemReportController.php b/app/Http/Controllers/Reports/InvoiceItemReportController.php index a124171cc6..847db7a339 100644 --- a/app/Http/Controllers/Reports/InvoiceItemReportController.php +++ b/app/Http/Controllers/Reports/InvoiceItemReportController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; use App\Export\CSV\InvoiceItemExport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class InvoiceItemReportController extends BaseController { @@ -72,26 +72,11 @@ class InvoiceItemReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), InvoiceItemExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), InvoiceItemExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new InvoiceItemExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/InvoiceReportController.php b/app/Http/Controllers/Reports/InvoiceReportController.php index c00687fb68..d6b8a0dc08 100644 --- a/app/Http/Controllers/Reports/InvoiceReportController.php +++ b/app/Http/Controllers/Reports/InvoiceReportController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Export\CSV\InvoiceExport; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class InvoiceReportController extends BaseController { @@ -72,27 +72,11 @@ class InvoiceReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), InvoiceExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), InvoiceExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - // expect a list of visible fields, or use the default - $export = new InvoiceExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/PaymentReportController.php b/app/Http/Controllers/Reports/PaymentReportController.php index cca6925ef9..27db61d231 100644 --- a/app/Http/Controllers/Reports/PaymentReportController.php +++ b/app/Http/Controllers/Reports/PaymentReportController.php @@ -11,14 +11,14 @@ namespace App\Http\Controllers\Reports; -use App\Models\Client; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Export\CSV\PaymentExport; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Models\Client; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class PaymentReportController extends BaseController { @@ -72,29 +72,13 @@ class PaymentReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), PaymentExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), PaymentExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new PaymentExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ProductReportController.php b/app/Http/Controllers/Reports/ProductReportController.php index 664bd51a69..fb48f5c523 100644 --- a/app/Http/Controllers/Reports/ProductReportController.php +++ b/app/Http/Controllers/Reports/ProductReportController.php @@ -11,14 +11,14 @@ namespace App\Http\Controllers\Reports; -use App\Models\Client; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Export\CSV\ProductExport; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Models\Client; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class ProductReportController extends BaseController { @@ -73,28 +73,12 @@ class ProductReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), ProductExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), ProductExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new ProductExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ProfitAndLossController.php b/app/Http/Controllers/Reports/ProfitAndLossController.php index 3d1f075106..26e860f16b 100644 --- a/app/Http/Controllers/Reports/ProfitAndLossController.php +++ b/app/Http/Controllers/Reports/ProfitAndLossController.php @@ -63,14 +63,17 @@ class ProfitAndLossController extends BaseController */ public function __invoke(ProfitLossRequest $request) { + /** @var \App\Models\User $user */ + $user = auth()->user(); + if ($request->has('send_email') && $request->get('send_email')) { - SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ProfitLoss::class, $this->filename); + SendToAdmin::dispatch($user->company(), $request->all(), ProfitLoss::class, $this->filename); return response()->json(['message' => 'working...'], 200); } // expect a list of visible fields, or use the default - $pnl = new ProfitLoss(auth()->user()->company(), $request->all()); + $pnl = new ProfitLoss($user->company(), $request->all()); $csv = $pnl->run(); $headers = [ diff --git a/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php b/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php index 71509576f5..b6ede66f16 100644 --- a/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php +++ b/app/Http/Controllers/Reports/PurchaseOrderItemReportController.php @@ -11,12 +11,12 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; -use App\Http\Controllers\BaseController; use App\Export\CSV\PurchaseOrderItemExport; +use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; class PurchaseOrderItemReportController extends BaseController { @@ -39,28 +39,12 @@ class PurchaseOrderItemReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderItemExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderItemExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new PurchaseOrderItemExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/PurchaseOrderReportController.php b/app/Http/Controllers/Reports/PurchaseOrderReportController.php index 5899b20cfc..c8d14be824 100644 --- a/app/Http/Controllers/Reports/PurchaseOrderReportController.php +++ b/app/Http/Controllers/Reports/PurchaseOrderReportController.php @@ -11,12 +11,12 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; use App\Export\CSV\PurchaseOrderExport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; class PurchaseOrderReportController extends BaseController { @@ -41,29 +41,12 @@ class PurchaseOrderReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - - $export = new PurchaseOrderExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/QuoteItemReportController.php b/app/Http/Controllers/Reports/QuoteItemReportController.php index 78295f1ddc..2fad0670c8 100644 --- a/app/Http/Controllers/Reports/QuoteItemReportController.php +++ b/app/Http/Controllers/Reports/QuoteItemReportController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; use App\Export\CSV\QuoteItemExport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class QuoteItemReportController extends BaseController { @@ -71,28 +71,12 @@ class QuoteItemReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), QuoteItemExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), QuoteItemExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new QuoteItemExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/QuoteReportController.php b/app/Http/Controllers/Reports/QuoteReportController.php index 9034b1a939..a215846aaa 100644 --- a/app/Http/Controllers/Reports/QuoteReportController.php +++ b/app/Http/Controllers/Reports/QuoteReportController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; use App\Export\CSV\QuoteExport; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class QuoteReportController extends BaseController { @@ -71,28 +71,12 @@ class QuoteReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), QuoteExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), QuoteExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new QuoteExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/RecurringInvoiceReportController.php b/app/Http/Controllers/Reports/RecurringInvoiceReportController.php index 26eb279106..7536b25611 100644 --- a/app/Http/Controllers/Reports/RecurringInvoiceReportController.php +++ b/app/Http/Controllers/Reports/RecurringInvoiceReportController.php @@ -11,13 +11,12 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; -use App\Http\Controllers\BaseController; use App\Export\CSV\RecurringInvoiceExport; +use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; class RecurringInvoiceReportController extends BaseController { @@ -40,28 +39,12 @@ class RecurringInvoiceReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), RecurringInvoiceExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), RecurringInvoiceExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new RecurringInvoiceExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ReportExportController.php b/app/Http/Controllers/Reports/ReportExportController.php new file mode 100644 index 0000000000..bb936668bc --- /dev/null +++ b/app/Http/Controllers/Reports/ReportExportController.php @@ -0,0 +1,56 @@ +json(['message' => 'Still working.....'], 409); + } + + if($report) { + + Cache::forget($hash); + + $headers = [ + 'Content-Disposition' => 'attachment', + 'Content-Type' => 'text/csv', + ]; + + return response()->streamDownload(function () use ($report) { + echo $report; + }, $this->filename, $headers); + + } + + + } +} diff --git a/app/Http/Controllers/Reports/ReportPreviewController.php b/app/Http/Controllers/Reports/ReportPreviewController.php index 82f55bc2f4..1bb559552c 100644 --- a/app/Http/Controllers/Reports/ReportPreviewController.php +++ b/app/Http/Controllers/Reports/ReportPreviewController.php @@ -11,10 +11,10 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use Illuminate\Support\Facades\Cache; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\ReportPreviewRequest; +use App\Utils\Traits\MakesHash; +use Illuminate\Support\Facades\Cache; class ReportPreviewController extends BaseController { @@ -30,10 +30,11 @@ class ReportPreviewController extends BaseController $report = Cache::get($hash); - if(!$report) + if(!$report) { return response()->json(['message' => 'Still working.....'], 409); + } - if($report){ + if($report) { Cache::forget($hash); diff --git a/app/Http/Controllers/Reports/TaskReportController.php b/app/Http/Controllers/Reports/TaskReportController.php index 8339a909bc..8293f863c5 100644 --- a/app/Http/Controllers/Reports/TaskReportController.php +++ b/app/Http/Controllers/Reports/TaskReportController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers\Reports; -use Illuminate\Http\Response; use App\Export\CSV\TaskExport; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class TaskReportController extends BaseController { @@ -71,28 +71,12 @@ class TaskReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), TaskExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), TaskExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new TaskExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/TaxSummaryReportController.php b/app/Http/Controllers/Reports/TaxSummaryReportController.php index 776fa988d6..b199eadcc1 100644 --- a/app/Http/Controllers/Reports/TaxSummaryReportController.php +++ b/app/Http/Controllers/Reports/TaxSummaryReportController.php @@ -11,12 +11,11 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Http\Controllers\BaseController; -use App\Services\Report\TaxSummaryReport; -use App\Services\Report\ClientSalesReport; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\SendToAdmin; +use App\Services\Report\TaxSummaryReport; +use App\Utils\Traits\MakesHash; class TaxSummaryReportController extends BaseController { diff --git a/app/Http/Controllers/Reports/UserSalesReportController.php b/app/Http/Controllers/Reports/UserSalesReportController.php index 582eb4e717..2d80995791 100644 --- a/app/Http/Controllers/Reports/UserSalesReportController.php +++ b/app/Http/Controllers/Reports/UserSalesReportController.php @@ -11,12 +11,11 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; -use App\Jobs\Report\SendToAdmin; use App\Http\Controllers\BaseController; -use App\Services\Report\UserSalesReport; -use App\Services\Report\TaxSummaryReport; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\SendToAdmin; +use App\Services\Report\UserSalesReport; +use App\Utils\Traits\MakesHash; class UserSalesReportController extends BaseController { diff --git a/app/Http/Controllers/Reports/VendorReportController.php b/app/Http/Controllers/Reports/VendorReportController.php index bfd0f3b229..d86f031df7 100644 --- a/app/Http/Controllers/Reports/VendorReportController.php +++ b/app/Http/Controllers/Reports/VendorReportController.php @@ -11,12 +11,12 @@ namespace App\Http\Controllers\Reports; -use App\Utils\Traits\MakesHash; use App\Export\CSV\VendorExport; -use App\Jobs\Report\SendToAdmin; -use App\Jobs\Report\PreviewReport; use App\Http\Controllers\BaseController; use App\Http\Requests\Report\GenericReportRequest; +use App\Jobs\Report\PreviewReport; +use App\Jobs\Report\SendToAdmin; +use App\Utils\Traits\MakesHash; class VendorReportController extends BaseController { @@ -39,28 +39,12 @@ class VendorReportController extends BaseController return response()->json(['message' => 'working...'], 200); } - // expect a list of visible fields, or use the default - if($request->has('output') && $request->input('output') == 'json') { + $hash = \Illuminate\Support\Str::uuid(); - $hash = \Illuminate\Support\Str::uuid(); + PreviewReport::dispatch($user->company(), $request->all(), VendorExport::class, $hash); - PreviewReport::dispatch($user->company(), $request->all(), VendorExport::class, $hash); + return response()->json(['message' => $hash], 200); - return response()->json(['message' => $hash], 200); - } - - $export = new VendorExport($user->company(), $request->all()); - - $csv = $export->run(); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($csv) { - echo $csv; - }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index cd985b44c7..7699e8c3d6 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -54,25 +54,25 @@ class SearchController extends Controller ->take(1000) ->get(); - foreach($clients as $client) { - $this->clients[] = [ - 'name' => $client->present()->name(), - 'type' => '/client', - 'id' => $client->hashed_id, - 'path' => "/clients/{$client->hashed_id}/edit" - ]; + foreach($clients as $client) { + $this->clients[] = [ + 'name' => $client->present()->name(), + 'type' => '/client', + 'id' => $client->hashed_id, + 'path' => "/clients/{$client->hashed_id}/edit" + ]; - $client->contacts->each(function ($contact) { - $this->client_contacts[] = [ - 'name' => $contact->present()->search_display(), - 'type' => '/client_contact', - 'id' => $contact->hashed_id, - 'path' => "/clients/{$contact->hashed_id}" - ]; + $client->contacts->each(function ($contact) { + $this->client_contacts[] = [ + 'name' => $contact->present()->search_display(), + 'type' => '/client_contact', + 'id' => $contact->hashed_id, + 'path' => "/clients/{$contact->hashed_id}" + ]; - }); - } + }); + } } @@ -92,16 +92,16 @@ class SearchController extends Controller }) ->orderBy('id', 'desc') ->take(3000) - ->get(); + ->get(); - foreach($invoices as $invoice) { - $this->invoices[] = [ - 'name' => $invoice->client->present()->name() . ' - ' . $invoice->number, - 'type' => '/invoice', - 'id' => $invoice->hashed_id, - 'path' => "/invoices/{$invoice->hashed_id}/edit" - ]; - } + foreach($invoices as $invoice) { + $this->invoices[] = [ + 'name' => $invoice->client->present()->name() . ' - ' . $invoice->number, + 'type' => '/invoice', + 'id' => $invoice->hashed_id, + 'path' => "/invoices/{$invoice->hashed_id}/edit" + ]; + } } diff --git a/app/Http/Controllers/SelfUpdateController.php b/app/Http/Controllers/SelfUpdateController.php index 75d2442fcd..651d884ac3 100644 --- a/app/Http/Controllers/SelfUpdateController.php +++ b/app/Http/Controllers/SelfUpdateController.php @@ -11,14 +11,14 @@ namespace App\Http\Controllers; -use App\Utils\Ninja; +use App\Exceptions\FilePermissionsFailure; use App\Models\Company; +use App\Utils\Ninja; use App\Utils\Traits\AppSetup; +use App\Utils\Traits\ClientGroupSettingsSaver; +use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Storage; -use App\Exceptions\FilePermissionsFailure; -use Illuminate\Foundation\Bus\DispatchesJobs; -use App\Utils\Traits\ClientGroupSettingsSaver; class SelfUpdateController extends BaseController { @@ -72,8 +72,7 @@ class SelfUpdateController extends BaseController if (copy($this->getDownloadUrl(), storage_path("app/{$this->filename}"))) { nlog('Copied file from URL'); } - } - catch(\Exception $e) { + } catch(\Exception $e) { nlog($e->getMessage()); return response()->json(['message' => 'File exists on the server, however there was a problem downloading and copying to the local filesystem'], 500); } @@ -121,18 +120,19 @@ class SelfUpdateController extends BaseController { Company::query() ->cursor() - ->each(function ($company){ + ->each(function ($company) { - $settings = $company->settings; + $settings = $company->settings; - if(property_exists($settings->pdf_variables, 'purchase_order_details')) - return; + if(property_exists($settings->pdf_variables, 'purchase_order_details')) { + return; + } - $pdf_variables = $settings->pdf_variables; - $pdf_variables->purchase_order_details = []; - $settings->pdf_variables = $pdf_variables; - $company->settings = $settings; - $company->save(); + $pdf_variables = $settings->pdf_variables; + $pdf_variables->purchase_order_details = []; + $settings->pdf_variables = $pdf_variables; + $company->settings = $settings; + $company->save(); }); } diff --git a/app/Http/Controllers/SetupController.php b/app/Http/Controllers/SetupController.php index c849e73480..e7ac3a6107 100644 --- a/app/Http/Controllers/SetupController.php +++ b/app/Http/Controllers/SetupController.php @@ -121,8 +121,7 @@ class SetupController extends Controller unset($env_values['DB_DATABASE']); unset($env_values['DB_USERNAME']); unset($env_values['DB_PASSWORD']); - } - else { + } else { config(['database.connections.mysql.host' => $request->input('db_host')]); config(['database.connections.mysql.port' => $request->input('db_port')]); diff --git a/app/Http/Controllers/Shop/ProfileController.php b/app/Http/Controllers/Shop/ProfileController.php index 975ca5cf34..4239baeaa2 100644 --- a/app/Http/Controllers/Shop/ProfileController.php +++ b/app/Http/Controllers/Shop/ProfileController.php @@ -28,7 +28,7 @@ class ProfileController extends BaseController public function show(Request $request) { - /** @var \App\Models\Company $company */ + /** @var \App\Models\Company $company */ $company = Company::where('company_key', $request->header('X-API-COMPANY-KEY'))->first(); if (! $company->enable_shop_api) { diff --git a/app/Http/Controllers/StripeConnectController.php b/app/Http/Controllers/StripeConnectController.php index edb97e486d..3a5f9ddd8e 100644 --- a/app/Http/Controllers/StripeConnectController.php +++ b/app/Http/Controllers/StripeConnectController.php @@ -123,7 +123,7 @@ class StripeConnectController extends BaseController $company_gateway->setConfig($payload); $company_gateway->save(); - try{ + try { $stripe = $company_gateway->driver()->init(); $a = \Stripe\Account::retrieve($response->stripe_user_id, $stripe->stripe_connect_auth); @@ -131,8 +131,7 @@ class StripeConnectController extends BaseController $company_gateway->label = substr("Stripe - {$a->business_name}", 0, 250); $company_gateway->save(); } - } - catch(\Exception $e){ + } catch(\Exception $e) { nlog("could not harvest stripe company name"); } diff --git a/app/Http/Controllers/TaskController.php b/app/Http/Controllers/TaskController.php index 1d722b86a2..a66c64424f 100644 --- a/app/Http/Controllers/TaskController.php +++ b/app/Http/Controllers/TaskController.php @@ -327,7 +327,7 @@ class TaskController extends BaseController * ) */ public function create(CreateTaskRequest $request) - { + { /** @var \App\Models\User $user */ $user = auth()->user(); @@ -506,7 +506,7 @@ class TaskController extends BaseController $tasks->each(function ($task, $key) use ($action) { /** @var \App\Models\User $user */ - $user = auth()->user(); + $user = auth()->user(); if ($user->can('edit', $task)) { $this->task_repo->{$action}($task); } @@ -633,7 +633,7 @@ class TaskController extends BaseController /** @var \App\Models\User $user */ $user = auth()->user(); - collect($task_statuses)->each(function ($task_status_hashed_id, $key) use($user){ + collect($task_statuses)->each(function ($task_status_hashed_id, $key) use ($user) { $task_status = TaskStatus::query()->where('id', $this->decodePrimaryKey($task_status_hashed_id)) ->where('company_id', $user->company()->id) ->withTrashed() diff --git a/app/Http/Controllers/TaskSchedulerController.php b/app/Http/Controllers/TaskSchedulerController.php index 24e19e9559..e206ca8e4e 100644 --- a/app/Http/Controllers/TaskSchedulerController.php +++ b/app/Http/Controllers/TaskSchedulerController.php @@ -22,7 +22,6 @@ use App\Models\Scheduler; use App\Repositories\SchedulerRepository; use App\Transformers\SchedulerTransformer; use App\Utils\Traits\MakesHash; -use Symfony\Component\HttpFoundation\Request; class TaskSchedulerController extends BaseController { diff --git a/app/Http/Controllers/TaskStatusController.php b/app/Http/Controllers/TaskStatusController.php index 836dc9f88a..db3d79f406 100644 --- a/app/Http/Controllers/TaskStatusController.php +++ b/app/Http/Controllers/TaskStatusController.php @@ -11,20 +11,20 @@ namespace App\Http\Controllers; -use App\Models\TaskStatus; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; use App\Factory\TaskStatusFactory; use App\Filters\TaskStatusFilters; -use App\Repositories\TaskStatusRepository; -use App\Transformers\TaskStatusTransformer; +use App\Http\Requests\TaskStatus\ActionTaskStatusRequest; +use App\Http\Requests\TaskStatus\CreateTaskStatusRequest; +use App\Http\Requests\TaskStatus\DestroyTaskStatusRequest; use App\Http\Requests\TaskStatus\EditTaskStatusRequest; use App\Http\Requests\TaskStatus\ShowTaskStatusRequest; use App\Http\Requests\TaskStatus\StoreTaskStatusRequest; -use App\Http\Requests\TaskStatus\ActionTaskStatusRequest; -use App\Http\Requests\TaskStatus\CreateTaskStatusRequest; use App\Http\Requests\TaskStatus\UpdateTaskStatusRequest; -use App\Http\Requests\TaskStatus\DestroyTaskStatusRequest; +use App\Models\TaskStatus; +use App\Repositories\TaskStatusRepository; +use App\Transformers\TaskStatusTransformer; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; class TaskStatusController extends BaseController { @@ -135,8 +135,9 @@ class TaskStatusController extends BaseController $reorder = $task_status->isDirty('status_order'); $task_status->save(); - if ($reorder) + if ($reorder) { $this->task_status_repo->reorder($task_status); + } return $this->itemResponse($task_status->fresh()); @@ -148,7 +149,7 @@ class TaskStatusController extends BaseController * @param DestroyTaskStatusRequest $request * @param TaskStatus $task_status * @return Response - * + * * @throws \Exception */ public function destroy(DestroyTaskStatusRequest $request, TaskStatus $task_status) diff --git a/app/Http/Controllers/TemplatePreviewController.php b/app/Http/Controllers/TemplatePreviewController.php new file mode 100644 index 0000000000..2cfd05ed8a --- /dev/null +++ b/app/Http/Controllers/TemplatePreviewController.php @@ -0,0 +1,51 @@ +exists($this->path_prefix.$hash.$this->path_suffix); + + if(!$report) { + return response()->json(['message' => 'Still working.....'], 409); + } + + Cache::forget($hash); + + return response()->streamDownload(function () use ($hash) { + + echo Storage::get($this->path_prefix.$hash.$this->path_suffix); + Storage::delete($this->path_prefix.$hash.$this->path_suffix); + + }, 'template.pdf', ['Content-Type' => 'application/pdf']); + + } +} diff --git a/app/Http/Controllers/Traits/VerifiesUserEmail.php b/app/Http/Controllers/Traits/VerifiesUserEmail.php index 7b26c9de39..f5796c51e9 100644 --- a/app/Http/Controllers/Traits/VerifiesUserEmail.php +++ b/app/Http/Controllers/Traits/VerifiesUserEmail.php @@ -36,7 +36,7 @@ trait VerifiesUserEmail if (! $user) { return $this->render('auth.confirmed', [ - 'root' => 'themes', + 'root' => 'themes', 'message' => ctrans('texts.wrong_confirmation'), 'redirect_url' => request()->has('react') ? config('ninja.react_url')."/#/" : url('/')]); } diff --git a/app/Http/Controllers/TwilioController.php b/app/Http/Controllers/TwilioController.php index d6bf7488d9..39b7f72637 100644 --- a/app/Http/Controllers/TwilioController.php +++ b/app/Http/Controllers/TwilioController.php @@ -11,13 +11,13 @@ namespace App\Http\Controllers; -use App\Models\User; -use Twilio\Rest\Client; -use App\Libraries\MultiDB; use App\Http\Requests\Twilio\Confirm2faRequest; use App\Http\Requests\Twilio\ConfirmSmsRequest; use App\Http\Requests\Twilio\Generate2faRequest; use App\Http\Requests\Twilio\GenerateSmsRequest; +use App\Libraries\MultiDB; +use App\Models\User; +use Twilio\Rest\Client; class TwilioController extends BaseController { diff --git a/app/Http/Controllers/TwoFactorController.php b/app/Http/Controllers/TwoFactorController.php index 9ba490a6f1..2d86469f9d 100644 --- a/app/Http/Controllers/TwoFactorController.php +++ b/app/Http/Controllers/TwoFactorController.php @@ -11,11 +11,11 @@ namespace App\Http\Controllers; +use App\Http\Requests\TwoFactor\EnableTwoFactorRequest; use App\Models\User; +use App\Transformers\UserTransformer; use App\Utils\Ninja; use PragmaRX\Google2FA\Google2FA; -use App\Transformers\UserTransformer; -use App\Http\Requests\TwoFactor\EnableTwoFactorRequest; class TwoFactorController extends BaseController { @@ -30,10 +30,9 @@ class TwoFactorController extends BaseController if ($user->google_2fa_secret) { return response()->json(['message' => '2FA already enabled'], 400); - } elseif(Ninja::isSelfHost()){ + } elseif(Ninja::isSelfHost()) { - } - elseif (! $user->phone) { + } elseif (! $user->phone) { return response()->json(['message' => ctrans('texts.set_phone_for_two_factor')], 400); } elseif (! $user->isVerified()) { return response()->json(['message' => 'Please confirm your account first'], 400); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 2c785dbc84..03f9f0584d 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -11,31 +11,31 @@ namespace App\Http\Controllers; -use App\Models\User; -use App\Utils\Ninja; -use App\Models\CompanyUser; -use App\Factory\UserFactory; -use App\Filters\UserFilters; -use Illuminate\Http\Response; -use App\Utils\Traits\MakesHash; use App\Events\User\UserWasCreated; use App\Events\User\UserWasDeleted; use App\Events\User\UserWasUpdated; -use App\Jobs\User\UserEmailChanged; -use App\Repositories\UserRepository; -use App\Transformers\UserTransformer; -use App\Jobs\Company\CreateCompanyToken; -use App\Http\Requests\User\BulkUserRequest; -use App\Http\Requests\User\EditUserRequest; -use App\Http\Requests\User\ShowUserRequest; -use App\Http\Requests\User\StoreUserRequest; -use App\Http\Requests\User\CreateUserRequest; -use App\Http\Requests\User\UpdateUserRequest; -use App\Http\Requests\User\DestroyUserRequest; -use App\Http\Requests\User\ReconfirmUserRequest; +use App\Factory\UserFactory; +use App\Filters\UserFilters; use App\Http\Controllers\Traits\VerifiesUserEmail; +use App\Http\Requests\User\BulkUserRequest; +use App\Http\Requests\User\CreateUserRequest; +use App\Http\Requests\User\DestroyUserRequest; use App\Http\Requests\User\DetachCompanyUserRequest; use App\Http\Requests\User\DisconnectUserMailerRequest; +use App\Http\Requests\User\EditUserRequest; +use App\Http\Requests\User\ReconfirmUserRequest; +use App\Http\Requests\User\ShowUserRequest; +use App\Http\Requests\User\StoreUserRequest; +use App\Http\Requests\User\UpdateUserRequest; +use App\Jobs\Company\CreateCompanyToken; +use App\Jobs\User\UserEmailChanged; +use App\Models\CompanyUser; +use App\Models\User; +use App\Repositories\UserRepository; +use App\Transformers\UserTransformer; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use Illuminate\Http\Response; /** * Class UserController. @@ -235,7 +235,7 @@ class UserController extends BaseController $return_user_collection = collect(); /** @var \App\Models\User $logged_in_user */ - $logged_in_user = auth()->user(); + $logged_in_user = auth()->user(); $users->each(function ($user, $key) use ($logged_in_user, $action, $return_user_collection) { if ($logged_in_user->can('edit', $user)) { diff --git a/app/Http/Controllers/VendorPortal/InvitationController.php b/app/Http/Controllers/VendorPortal/InvitationController.php index 7ce6ae394d..81bffff02d 100644 --- a/app/Http/Controllers/VendorPortal/InvitationController.php +++ b/app/Http/Controllers/VendorPortal/InvitationController.php @@ -11,17 +11,16 @@ namespace App\Http\Controllers\VendorPortal; -use App\Utils\Ninja; -use Illuminate\Support\Str; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\MakesDates; -use Illuminate\Support\Facades\App; -use App\Http\Controllers\Controller; -use Illuminate\Support\Facades\Auth; -use App\Models\PurchaseOrderInvitation; use App\Events\Misc\InvitationWasViewed; -use App\Jobs\Vendor\CreatePurchaseOrderPdf; use App\Events\PurchaseOrder\PurchaseOrderWasViewed; +use App\Http\Controllers\Controller; +use App\Models\PurchaseOrderInvitation; +use App\Utils\Ninja; +use App\Utils\Traits\MakesDates; +use App\Utils\Traits\MakesHash; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Str; /** * Class InvitationController. @@ -94,7 +93,7 @@ class InvitationController extends Controller $file_name = $invitation->purchase_order->numberFormatter().'.pdf'; - $file = (new CreatePurchaseOrderPdf($invitation))->rawPdf(); + $file = $invitation->purchase_order->service()->getPurchaseOrderPdf(); $headers = ['Content-Type' => 'application/pdf']; diff --git a/app/Http/Controllers/VendorPortal/PurchaseOrderController.php b/app/Http/Controllers/VendorPortal/PurchaseOrderController.php index 74d66f0542..fb70c248b7 100644 --- a/app/Http/Controllers/VendorPortal/PurchaseOrderController.php +++ b/app/Http/Controllers/VendorPortal/PurchaseOrderController.php @@ -16,13 +16,13 @@ use Illuminate\View\View; use App\Models\PurchaseOrder; use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesDates; +use App\Jobs\Entity\CreateRawPdf; use App\Http\Controllers\Controller; use App\Jobs\Invoice\InjectSignature; use Illuminate\Support\Facades\Cache; use Illuminate\Contracts\View\Factory; use App\Models\PurchaseOrderInvitation; use App\Events\Misc\InvitationWasViewed; -use App\Jobs\Vendor\CreatePurchaseOrderPdf; use App\Events\PurchaseOrder\PurchaseOrderWasViewed; use App\Events\PurchaseOrder\PurchaseOrderWasAccepted; use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrderRequest; @@ -116,7 +116,7 @@ class PurchaseOrderController extends Controller $invitation = PurchaseOrderInvitation::withTrashed()->find($data['invitation_id']); - $file = (new CreatePurchaseOrderPdf($invitation, $invitation->company->db))->rawPdf(); + $file = $invitation->purchase_order->service()->getPurchaseOrderPdf(); $headers = ['Content-Type' => 'application/pdf']; @@ -184,7 +184,7 @@ class PurchaseOrderController extends Controller } event(new PurchaseOrderWasAccepted($purchase_order, auth()->guard('vendor')->user(), $purchase_order->company, Ninja::eventVars())); - }); + }); if ($purchase_count_query->count() == 1) { $purchase_order = $purchase_count_query->first(); @@ -211,7 +211,8 @@ class PurchaseOrderController extends Controller if (count($purchase_order_invitations) == 1) { $invitation = $purchase_order_invitations->first(); - $file = (new CreatePurchaseOrderPdf($invitation, $invitation->company->db))->rawPdf(); + $file = (new CreateRawPdf($invitation))->handle(); + return response()->streamDownload(function () use ($file) { echo $file; }, $invitation->purchase_order->numberFormatter().".pdf", ['Content-Type' => 'application/pdf']); @@ -226,7 +227,8 @@ class PurchaseOrderController extends Controller $zipFile = new \PhpZip\ZipFile(); try { foreach ($invitations as $invitation) { - $file = (new CreatePurchaseOrderPdf($invitation, $invitation->company->db))->rawPdf(); + + $file = (new CreateRawPdf($invitation))->handle(); $zipFile->addFromString($invitation->purchase_order->numberFormatter().".pdf", $file); } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 1716268271..6a53796f3b 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -11,53 +11,52 @@ namespace App\Http; -use App\Utils\Ninja; -use App\Http\Middleware\Cors; -use App\Http\Middleware\SetDb; -use App\Http\Middleware\Locale; -use App\Http\Middleware\SetWebDb; -use App\Http\Middleware\UrlSetDb; -use App\Http\Middleware\TokenAuth; -use App\Http\Middleware\SetEmailDb; -use App\Http\Middleware\VerifyHash; -use App\Http\Middleware\SetInviteDb; -use App\Http\Middleware\TrimStrings; -use App\Http\Middleware\Authenticate; -use App\Http\Middleware\ContactSetDb; -use App\Http\Middleware\QueryLogging; -use App\Http\Middleware\TrustProxies; -use App\Http\Middleware\UserVerified; -use App\Http\Middleware\VendorLocale; -use App\Http\Middleware\PhantomSecret; -use App\Http\Middleware\SetDocumentDb; use App\Http\Middleware\ApiSecretCheck; +use App\Http\Middleware\Authenticate; +use App\Http\Middleware\CheckClientExistence; +use App\Http\Middleware\CheckForMaintenanceMode; +use App\Http\Middleware\ClientPortalEnabled; use App\Http\Middleware\ContactAccount; -use App\Http\Middleware\EncryptCookies; -use App\Http\Middleware\SessionDomains; use App\Http\Middleware\ContactKeyLogin; use App\Http\Middleware\ContactRegister; -use App\Http\Middleware\SetDomainNameDb; -use App\Http\Middleware\VerifyCsrfToken; +use App\Http\Middleware\ContactSetDb; use App\Http\Middleware\ContactTokenAuth; -use Illuminate\Auth\Middleware\Authorize; -use App\Http\Middleware\SetDbByCompanyKey; -use App\Http\Middleware\ValidateSignature; +use App\Http\Middleware\Cors; +use App\Http\Middleware\EncryptCookies; +use App\Http\Middleware\Locale; use App\Http\Middleware\PasswordProtection; -use App\Http\Middleware\ClientPortalEnabled; -use App\Http\Middleware\CheckClientExistence; -use App\Http\Middleware\VendorContactKeyLogin; -use Illuminate\Http\Middleware\SetCacheHeaders; -use Illuminate\Session\Middleware\StartSession; -use App\Http\Middleware\CheckForMaintenanceMode; +use App\Http\Middleware\PhantomSecret; +use App\Http\Middleware\QueryLogging; use App\Http\Middleware\RedirectIfAuthenticated; -use Illuminate\Foundation\Http\Kernel as HttpKernel; -use Illuminate\Auth\Middleware\EnsureEmailIsVerified; -use Illuminate\Routing\Middleware\SubstituteBindings; -use Illuminate\View\Middleware\ShareErrorsFromSession; +use App\Http\Middleware\SessionDomains; +use App\Http\Middleware\SetDb; +use App\Http\Middleware\SetDbByCompanyKey; +use App\Http\Middleware\SetDocumentDb; +use App\Http\Middleware\SetDomainNameDb; +use App\Http\Middleware\SetEmailDb; +use App\Http\Middleware\SetInviteDb; +use App\Http\Middleware\SetWebDb; +use App\Http\Middleware\TokenAuth; +use App\Http\Middleware\TrimStrings; +use App\Http\Middleware\TrustProxies; +use App\Http\Middleware\UrlSetDb; +use App\Http\Middleware\UserVerified; +use App\Http\Middleware\ValidateSignature; +use App\Http\Middleware\VendorContactKeyLogin; +use App\Http\Middleware\VendorLocale; +use App\Http\Middleware\VerifyCsrfToken; +use App\Http\Middleware\VerifyHash; use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; -use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use Illuminate\Auth\Middleware\Authorize; +use Illuminate\Auth\Middleware\EnsureEmailIsVerified; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; +use Illuminate\Foundation\Http\Kernel as HttpKernel; use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; +use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use Illuminate\Http\Middleware\SetCacheHeaders; +use Illuminate\Routing\Middleware\SubstituteBindings; +use Illuminate\Session\Middleware\StartSession; +use Illuminate\View\Middleware\ShareErrorsFromSession; class Kernel extends HttpKernel { diff --git a/app/Http/Livewire/BillingPortalPurchase.php b/app/Http/Livewire/BillingPortalPurchase.php index f8e625e03c..caa9b4b195 100644 --- a/app/Http/Livewire/BillingPortalPurchase.php +++ b/app/Http/Livewire/BillingPortalPurchase.php @@ -23,7 +23,6 @@ use App\Models\Invoice; use App\Models\Subscription; use App\Repositories\ClientContactRepository; use App\Repositories\ClientRepository; -use App\Services\Subscription\SubscriptionService; use App\Utils\Ninja; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; diff --git a/app/Http/Livewire/PdfSlot.php b/app/Http/Livewire/PdfSlot.php index 3ca80bd22e..91a51e588a 100644 --- a/app/Http/Livewire/PdfSlot.php +++ b/app/Http/Livewire/PdfSlot.php @@ -12,21 +12,20 @@ namespace App\Http\Livewire; -use App\Utils\Number; -use Livewire\Component; -use App\Utils\HtmlEngine; +use App\Jobs\Invoice\CreateEInvoice; use App\Libraries\MultiDB; -use Illuminate\Support\Str; -use App\Models\QuoteInvitation; -use App\Utils\VendorHtmlEngine; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; -use App\Jobs\Invoice\CreateEInvoice; -use Illuminate\Support\Facades\Cache; use App\Models\PurchaseOrderInvitation; +use App\Models\QuoteInvitation; use App\Models\RecurringInvoiceInvitation; -use App\Jobs\Vendor\CreatePurchaseOrderPdf; use App\Services\PdfMaker\Designs\Utilities\DesignHelpers; +use App\Utils\HtmlEngine; +use App\Utils\Number; +use App\Utils\VendorHtmlEngine; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Str; +use Livewire\Component; class PdfSlot extends Component { @@ -70,6 +69,11 @@ class PdfSlot extends Component public function getPdf() { + if(!$this->invitation) { + $this->entity->service()->createInvitations(); + $this->invitation = $this->entity->invitations()->first(); + } + $blob = [ 'entity_type' => $this->resolveEntityType(), 'entity_id' => $this->entity->id, @@ -90,10 +94,7 @@ class PdfSlot extends Component $file_name = $this->entity->numberFormatter().'.pdf'; - if($this->entity instanceof \App\Models\PurchaseOrder) - $file = (new CreatePurchaseOrderPdf($this->invitation, $this->invitation->company->db))->rawPdf(); - else - $file = (new \App\Jobs\Entity\CreateRawPdf($this->invitation, $this->invitation->company->db))->handle(); + $file = (new \App\Jobs\Entity\CreateRawPdf($this->invitation))->handle(); $headers = ['Content-Type' => 'application/pdf']; @@ -102,6 +103,7 @@ class PdfSlot extends Component }, $file_name, $headers); } + public function downloadEInvoice() { @@ -128,7 +130,7 @@ class PdfSlot extends Component $this->show_line_total = in_array('$product.line_total', $this->settings->pdf_variables->product_columns); $this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_columns); - if($this->entity_type == 'quote' && !$this->settings->sync_invoice_quote_columns ){ + if($this->entity_type == 'quote' && !$this->settings->sync_invoice_quote_columns) { $this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_quote_columns); $this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_quote_columns); $this->show_line_total = in_array('$product.line_total', $this->settings->pdf_variables->product_quote_columns); @@ -195,21 +197,22 @@ class PdfSlot extends Component $entity_details = ""; if($this->entity_type == 'invoice' || $this->entity_type == 'recurring_invoice') { - foreach($this->settings->pdf_variables->invoice_details as $variable) + foreach($this->settings->pdf_variables->invoice_details as $variable) { $entity_details .= "
{$variable}_label
{$variable}
{$variable}_label
{$variable}
{$variable}_label
{$variable}
{$variable}_label
{$variable}
{$variable}
"; } - } - else{ - foreach(array_slice($this->settings->pdf_variables->client_details,1) as $variable) { + } else { + foreach(array_slice($this->settings->pdf_variables->client_details, 1) as $variable) { $user_details .= "{$variable}
"; } } @@ -255,7 +257,7 @@ class PdfSlot extends Component $product_items = collect($this->entity->line_items)->filter(function ($item) { return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5; - })->map(function ($item){ + })->map(function ($item) { $notes = strlen($item->notes) > 4 ? $item->notes : $item->product_key; @@ -274,7 +276,7 @@ class PdfSlot extends Component { $task_items = collect($this->entity->line_items)->filter(function ($item) { return $item->type_id == 2; - })->map(function ($item){ + })->map(function ($item) { return [ 'quantity' => $item->quantity, 'cost' => Number::formatMoney($item->cost, $this->entity->client ?: $this->entity->vendor), diff --git a/app/Http/Livewire/TasksTable.php b/app/Http/Livewire/TasksTable.php index f229db889f..fa3f45df6e 100644 --- a/app/Http/Livewire/TasksTable.php +++ b/app/Http/Livewire/TasksTable.php @@ -39,11 +39,11 @@ class TasksTable extends Component ->where('is_deleted', false) ->where('client_id', auth()->guard('contact')->user()->client_id); - if ( auth()->guard('contact')->user()->client->getSetting('show_all_tasks_client_portal') === 'invoiced') { + if (auth()->guard('contact')->user()->client->getSetting('show_all_tasks_client_portal') === 'invoiced') { $query = $query->whereNotNull('invoice_id'); } - if ( auth()->guard('contact')->user()->client->getSetting('show_all_tasks_client_portal') === 'uninvoiced') { + if (auth()->guard('contact')->user()->client->getSetting('show_all_tasks_client_portal') === 'uninvoiced') { $query = $query->whereNull('invoice_id'); } diff --git a/app/Http/Middleware/PasswordProtection.php b/app/Http/Middleware/PasswordProtection.php index 4450ec3210..d34c817f2a 100644 --- a/app/Http/Middleware/PasswordProtection.php +++ b/app/Http/Middleware/PasswordProtection.php @@ -38,7 +38,7 @@ class PasswordProtection ]; /** @var \App\Models\User auth()->user() */ - $user = auth()->user(); + $user = auth()->user(); $timeout = $user->company()->default_password_timeout; if ($timeout == 0) { @@ -59,11 +59,9 @@ class PasswordProtection Cache::put(auth()->user()->hashed_id.'_'.auth()->user()->account_id.'_logged_in', Str::random(64), $timeout); return $next($request); - } - elseif(strlen(auth()->user()->oauth_provider_id) > 2 && !auth()->user()->company()->oauth_password_required){ + } elseif(strlen(auth()->user()->oauth_provider_id) > 2 && !auth()->user()->company()->oauth_password_required) { return $next($request); - } - elseif ($request->header('X-API-OAUTH-PASSWORD') && strlen($request->header('X-API-OAUTH-PASSWORD')) >=1) { + } elseif ($request->header('X-API-OAUTH-PASSWORD') && strlen($request->header('X-API-OAUTH-PASSWORD')) >=1) { //user is attempting to reauth with OAuth - check the token value //todo expand this to include all OAuth providers if (auth()->user()->oauth_provider_id == 'google') { diff --git a/app/Http/Middleware/QueryLogging.php b/app/Http/Middleware/QueryLogging.php index e6aa71a7b8..39fac1a5a6 100644 --- a/app/Http/Middleware/QueryLogging.php +++ b/app/Http/Middleware/QueryLogging.php @@ -47,8 +47,9 @@ class QueryLogging public function terminate($request, $response) { - if (! Ninja::isHosted() || ! config('beacon.enabled')) + if (! Ninja::isHosted() || ! config('beacon.enabled')) { return; + } // hide requests made by debugbar if (strstr($request->url(), '_debugbar') === false) { diff --git a/app/Http/Middleware/TokenAuth.php b/app/Http/Middleware/TokenAuth.php index e73ccb00fc..227d47a380 100644 --- a/app/Http/Middleware/TokenAuth.php +++ b/app/Http/Middleware/TokenAuth.php @@ -31,7 +31,7 @@ class TokenAuth public function handle($request, Closure $next) { if ($request->header('X-API-TOKEN') && ($company_token = CompanyToken::with([ - 'user' => [ + 'user' => [ 'account', ], 'company'])->where('token', $request->header('X-API-TOKEN'))->first())) { $user = $company_token->user; diff --git a/app/Http/Middleware/UserVerified.php b/app/Http/Middleware/UserVerified.php index c951c13f3a..e45acb74c7 100644 --- a/app/Http/Middleware/UserVerified.php +++ b/app/Http/Middleware/UserVerified.php @@ -21,10 +21,9 @@ use Illuminate\Http\Request; */ class UserVerified { - public $user; - - public function __construct(?User $user) + public function __construct(public ?User $user) { + $this->user = property_exists($user, 'id') ? $user : auth()->user(); } diff --git a/app/Http/Middleware/ValidateSignature.php b/app/Http/Middleware/ValidateSignature.php index 6308b30862..deb5f45679 100644 --- a/app/Http/Middleware/ValidateSignature.php +++ b/app/Http/Middleware/ValidateSignature.php @@ -11,7 +11,6 @@ namespace App\Http\Middleware; - use Closure; use Illuminate\Routing\Exceptions\InvalidSignatureException; diff --git a/app/Http/Middleware/VendorContactKeyLogin.php b/app/Http/Middleware/VendorContactKeyLogin.php index e73a325546..407665e59f 100644 --- a/app/Http/Middleware/VendorContactKeyLogin.php +++ b/app/Http/Middleware/VendorContactKeyLogin.php @@ -11,14 +11,14 @@ namespace App\Http\Middleware; +use App\Libraries\MultiDB; +use App\Models\Vendor; +use App\Models\VendorContact; use Auth; use Closure; -use App\Models\Vendor; -use App\Libraries\MultiDB; -use Illuminate\Support\Str; use Illuminate\Http\Request; -use App\Models\VendorContact; use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Str; class VendorContactKeyLogin { diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 115de351c7..cbbd75224b 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -12,7 +12,6 @@ namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; -use Illuminate\Session\TokenMismatchException; class VerifyCsrfToken extends Middleware { diff --git a/app/Http/Requests/Activity/ShowActivityRequest.php b/app/Http/Requests/Activity/ShowActivityRequest.php index 219844f35d..a2a13eae6f 100644 --- a/app/Http/Requests/Activity/ShowActivityRequest.php +++ b/app/Http/Requests/Activity/ShowActivityRequest.php @@ -40,8 +40,9 @@ class ShowActivityRequest extends Request { $input = $this->all(); - if(isset($input['entity_id'])) + if(isset($input['entity_id'])) { $input['entity_id'] = $this->decodePrimaryKey($input['entity_id']); + } $this->replace($input); diff --git a/app/Http/Requests/ClientPortal/Invoices/ProcessInvoicesInBulkRequest.php b/app/Http/Requests/ClientPortal/Invoices/ProcessInvoicesInBulkRequest.php index 73724da000..7f855ef8de 100644 --- a/app/Http/Requests/ClientPortal/Invoices/ProcessInvoicesInBulkRequest.php +++ b/app/Http/Requests/ClientPortal/Invoices/ProcessInvoicesInBulkRequest.php @@ -33,7 +33,7 @@ class ProcessInvoicesInBulkRequest extends FormRequest { $input = $this->all(); - if(isset($input['invoices'])){ + if(isset($input['invoices'])) { $input['invoices'] = array_unique($input['invoices']); } diff --git a/app/Http/Requests/Company/UpdateCompanyRequest.php b/app/Http/Requests/Company/UpdateCompanyRequest.php index 9f64e4a284..4ffa0e3309 100644 --- a/app/Http/Requests/Company/UpdateCompanyRequest.php +++ b/app/Http/Requests/Company/UpdateCompanyRequest.php @@ -63,8 +63,9 @@ class UpdateCompanyRequest extends Request $rules['portal_domain'] = 'sometimes|url'; } - if (Ninja::isHosted()) + if (Ninja::isHosted()) { $rules['subdomain'] = ['nullable', 'regex:/^[a-zA-Z0-9.-]+[a-zA-Z0-9]$/', new ValidSubdomain()]; + } return $rules; } diff --git a/app/Http/Requests/CompanyGateway/BulkCompanyGatewayRequest.php b/app/Http/Requests/CompanyGateway/BulkCompanyGatewayRequest.php index 444bf89291..397734aed5 100644 --- a/app/Http/Requests/CompanyGateway/BulkCompanyGatewayRequest.php +++ b/app/Http/Requests/CompanyGateway/BulkCompanyGatewayRequest.php @@ -26,13 +26,20 @@ class BulkCompanyGatewayRequest extends Request */ public function authorize() : bool { - return auth()->user()->isAdmin(); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->isAdmin(); } public function rules() { + + /** @var \App\Models\User $user */ + $user = auth()->user(); + return [ - 'ids' => ['required','bail','array',Rule::exists('company_gateways', 'id')->where('company_id', auth()->user()->company()->id)], + 'ids' => ['required','bail','array',Rule::exists('company_gateways', 'id')->where('company_id', $user->company()->id)], 'action' => 'required|bail|in:archive,restore,delete' ]; } diff --git a/app/Http/Requests/Design/StoreDesignRequest.php b/app/Http/Requests/Design/StoreDesignRequest.php index 2af551664c..63d2b17911 100644 --- a/app/Http/Requests/Design/StoreDesignRequest.php +++ b/app/Http/Requests/Design/StoreDesignRequest.php @@ -16,6 +16,11 @@ use App\Models\Account; class StoreDesignRequest extends Request { + + private array $valid_entities = [ + 'invoice', + ]; + /** * Determine if the user is authorized to make this request. * @@ -23,20 +28,29 @@ class StoreDesignRequest extends Request */ public function authorize() : bool { - return auth()->user()->isAdmin() && auth()->user()->account->hasFeature(Account::FEATURE_API); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->isAdmin() && $user->account->hasFeature(Account::FEATURE_API); ; } public function rules() { + + /** @var \App\Models\User $user */ + $user = auth()->user(); + return [ //'name' => 'required', - 'name' => 'required|unique:designs,name,null,null,company_id,'.auth()->user()->companyId(), + 'name' => 'required|unique:designs,name,null,null,company_id,'.$user->companyId(), 'design' => 'required|array', - 'design.header' => 'required|min:1', - 'design.body' => 'required|min:1', - 'design.footer' => 'required|min:1', - 'design.includes' => 'required|min:1', + 'design.header' => 'sometimes|string', + 'design.body' => 'sometimes|string', + 'design.footer' => 'sometimes|string', + 'design.includes' => 'sometimes|string', + 'is_template' => 'sometimes|boolean', + 'entities' => 'sometimes|string|nullable' ]; } @@ -69,6 +83,20 @@ class StoreDesignRequest extends Request $input['design']['body'] = ''; } + if(array_key_exists('entities', $input)) { + $user_entities = explode(",", $input['entities']); + + $e = []; + + foreach ($user_entities as $entity) { + if (in_array($entity, $this->valid_entities)) { + $e[] = $entity; + } + } + + $input['entities'] = implode(",", $e); + } + $this->replace($input); } } diff --git a/app/Http/Requests/Design/UpdateDesignRequest.php b/app/Http/Requests/Design/UpdateDesignRequest.php index bae0d93d92..07fb4e68ea 100644 --- a/app/Http/Requests/Design/UpdateDesignRequest.php +++ b/app/Http/Requests/Design/UpdateDesignRequest.php @@ -18,6 +18,10 @@ class UpdateDesignRequest extends Request { use ChecksEntityStatus; + private array $valid_entities = [ + 'invoice', + ]; + /** * Determine if the user is authorized to make this request. * @@ -25,12 +29,18 @@ class UpdateDesignRequest extends Request */ public function authorize() : bool { - return auth()->user()->isAdmin(); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->isAdmin(); } public function rules() { - return []; + return [ + 'is_template' => 'sometimes|boolean', + 'entities' => 'sometimes|string|nullable' + ]; } public function prepareForValidation() @@ -61,6 +71,21 @@ class UpdateDesignRequest extends Request $input['design']['body'] = ''; } + if(array_key_exists('entities', $input)) { + $user_entities = explode(",", $input['entities']); + + $e = []; + + foreach ($user_entities as $entity) { + if (in_array($entity, $this->valid_entities)) { + $e[] = $entity; + } + } + + $input['entities'] = implode(",", $e); + } + + $this->replace($input); } } diff --git a/app/Http/Requests/Document/StoreDocumentRequest.php b/app/Http/Requests/Document/StoreDocumentRequest.php index f31504615d..7c3d4356f6 100644 --- a/app/Http/Requests/Document/StoreDocumentRequest.php +++ b/app/Http/Requests/Document/StoreDocumentRequest.php @@ -40,8 +40,9 @@ class StoreDocumentRequest extends Request { $input = $this->all(); - if(isset($input['is_public'])) + if(isset($input['is_public'])) { $input['is_public'] = $this->toBoolean($input['is_public']); + } $this->replace($input); } diff --git a/app/Http/Requests/Document/UpdateDocumentRequest.php b/app/Http/Requests/Document/UpdateDocumentRequest.php index bfa876eca2..3dcf677a6a 100644 --- a/app/Http/Requests/Document/UpdateDocumentRequest.php +++ b/app/Http/Requests/Document/UpdateDocumentRequest.php @@ -44,8 +44,9 @@ class UpdateDocumentRequest extends Request { $input = $this->all(); - if(isset($input['is_public'])) + if(isset($input['is_public'])) { $input['is_public'] = $this->toBoolean($input['is_public']); + } $this->replace($input); } diff --git a/app/Http/Requests/Email/ClientEmailHistoryRequest.php b/app/Http/Requests/Email/ClientEmailHistoryRequest.php index 45d60b458b..24d96a6e0b 100644 --- a/app/Http/Requests/Email/ClientEmailHistoryRequest.php +++ b/app/Http/Requests/Email/ClientEmailHistoryRequest.php @@ -13,7 +13,6 @@ namespace App\Http\Requests\Email; use App\Http\Requests\Request; use App\Utils\Traits\MakesHash; -use Illuminate\Support\Str; class ClientEmailHistoryRequest extends Request { diff --git a/app/Http/Requests/Email/EntityEmailHistoryRequest.php b/app/Http/Requests/Email/EntityEmailHistoryRequest.php index 2c506e653d..61bdf94033 100644 --- a/app/Http/Requests/Email/EntityEmailHistoryRequest.php +++ b/app/Http/Requests/Email/EntityEmailHistoryRequest.php @@ -11,9 +11,9 @@ namespace App\Http\Requests\Email; -use Illuminate\Support\Str; use App\Http\Requests\Request; use App\Utils\Traits\MakesHash; +use Illuminate\Support\Str; use Illuminate\Validation\Rule; class EntityEmailHistoryRequest extends Request diff --git a/app/Http/Requests/Email/SendEmailRequest.php b/app/Http/Requests/Email/SendEmailRequest.php index d917742dfa..53a48cc528 100644 --- a/app/Http/Requests/Email/SendEmailRequest.php +++ b/app/Http/Requests/Email/SendEmailRequest.php @@ -108,8 +108,7 @@ class SendEmailRequest extends Request if ($entity_obj && ($company->id == $entity_obj->company_id) && $user->can('edit', $entity_obj)) { return true; } - } - else { + } else { $this->error_message = "Invalid entity or entity_id"; } diff --git a/app/Http/Requests/GroupSetting/StoreGroupSettingRequest.php b/app/Http/Requests/GroupSetting/StoreGroupSettingRequest.php index d35e7ac2bc..b39f11533a 100644 --- a/app/Http/Requests/GroupSetting/StoreGroupSettingRequest.php +++ b/app/Http/Requests/GroupSetting/StoreGroupSettingRequest.php @@ -11,13 +11,13 @@ namespace App\Http\Requests\GroupSetting; -use App\Models\Account; -use App\Models\GroupSetting; -use App\Http\Requests\Request; use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; use App\DataMapper\Settings\SettingsData; +use App\Http\Requests\Request; use App\Http\ValidationRules\ValidClientGroupSettingsRule; +use App\Models\Account; +use App\Models\GroupSetting; class StoreGroupSettingRequest extends Request { @@ -52,8 +52,7 @@ class StoreGroupSettingRequest extends Request if (array_key_exists('settings', $input)) { $input['settings'] = $this->filterSaveableSettings($input['settings']); - } - else { + } else { $input['settings'] = (array)ClientSettings::defaults(); } diff --git a/app/Http/Requests/GroupSetting/UpdateGroupSettingRequest.php b/app/Http/Requests/GroupSetting/UpdateGroupSettingRequest.php index a264d74c01..ebb6f550fb 100644 --- a/app/Http/Requests/GroupSetting/UpdateGroupSettingRequest.php +++ b/app/Http/Requests/GroupSetting/UpdateGroupSettingRequest.php @@ -11,9 +11,9 @@ namespace App\Http\Requests\GroupSetting; -use App\Http\Requests\Request; use App\DataMapper\CompanySettings; use App\DataMapper\Settings\SettingsData; +use App\Http\Requests\Request; use App\Http\ValidationRules\ValidClientGroupSettingsRule; class UpdateGroupSettingRequest extends Request diff --git a/app/Http/Requests/Invoice/BulkInvoiceRequest.php b/app/Http/Requests/Invoice/BulkInvoiceRequest.php index 68554d1ee7..c46fe6db80 100644 --- a/app/Http/Requests/Invoice/BulkInvoiceRequest.php +++ b/app/Http/Requests/Invoice/BulkInvoiceRequest.php @@ -25,7 +25,10 @@ class BulkInvoiceRequest extends Request return [ 'action' => 'required|string', 'ids' => 'required|array', - 'email_type' => 'sometimes|in:reminder1,reminder2,reminder3,reminder_endless,custom1,custom2,custom3,invoice,quote,credit,payment,payment_partial,statement,purchase_order' + 'email_type' => 'sometimes|in:reminder1,reminder2,reminder3,reminder_endless,custom1,custom2,custom3,invoice,quote,credit,payment,payment_partial,statement,purchase_order', + 'template' => 'sometimes|string', + 'template_id' => 'sometimes|string', + 'send_email' => 'sometimes|bool' ]; } } diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php index 10ab3a1765..0cf37f68e6 100644 --- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php +++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php @@ -54,7 +54,7 @@ class StoreInvoiceRequest extends Request } elseif ($this->file('file')) { $rules['file'] = $this->file_validation; } - + $rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0'; $rules['invitations.*.client_contact_id'] = 'distinct'; @@ -73,6 +73,8 @@ class StoreInvoiceRequest extends Request $rules['tax_name2'] = 'bail|sometimes|string|nullable'; $rules['tax_name3'] = 'bail|sometimes|string|nullable'; $rules['exchange_rate'] = 'bail|sometimes|numeric'; + $rules['partial'] = 'bail|sometimes|nullable|numeric'; + $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date']; return $rules; } diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 859924029a..25c7c2fb2f 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -31,7 +31,7 @@ class UpdateInvoiceRequest extends Request * @return bool */ public function authorize() : bool - { + { /** @var \App\Models\User $user */ $user = auth()->user(); @@ -76,6 +76,8 @@ class UpdateInvoiceRequest extends Request $rules['tax_name3'] = 'bail|sometimes|string|nullable'; $rules['status_id'] = 'bail|sometimes|not_in:5'; //do not allow cancelled invoices to be modfified. $rules['exchange_rate'] = 'bail|sometimes|numeric'; + $rules['partial'] = 'bail|sometimes|nullable|numeric'; + $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date']; return $rules; } diff --git a/app/Http/Requests/Invoice/UploadInvoiceRequest.php b/app/Http/Requests/Invoice/UploadInvoiceRequest.php index 45d97b0799..1da7f3e829 100644 --- a/app/Http/Requests/Invoice/UploadInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UploadInvoiceRequest.php @@ -12,7 +12,6 @@ namespace App\Http\Requests\Invoice; use App\Http\Requests\Request; -use Illuminate\Http\UploadedFile; class UploadInvoiceRequest extends Request { diff --git a/app/Http/Requests/Payment/RefundPaymentRequest.php b/app/Http/Requests/Payment/RefundPaymentRequest.php index 5f0a8381d5..5a6f71d4cb 100644 --- a/app/Http/Requests/Payment/RefundPaymentRequest.php +++ b/app/Http/Requests/Payment/RefundPaymentRequest.php @@ -58,7 +58,7 @@ class RefundPaymentRequest extends Request if (isset($input['credits'])) { unset($input['credits']); // foreach($input['credits'] as $key => $credit) - // $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($credit['credit_id']); + // $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($credit['credit_id']); } $this->replace($input); diff --git a/app/Http/Requests/Payment/UpdatePaymentRequest.php b/app/Http/Requests/Payment/UpdatePaymentRequest.php index 02b465638e..113bf94932 100644 --- a/app/Http/Requests/Payment/UpdatePaymentRequest.php +++ b/app/Http/Requests/Payment/UpdatePaymentRequest.php @@ -82,8 +82,8 @@ class UpdatePaymentRequest extends Request if (isset($input['invoices']) && is_array($input['invoices']) !== false) { foreach ($input['invoices'] as $key => $value) { - if(isset($input['invoices'][$key]['invoice_id'])){ - // if (array_key_exists('invoice_id', $input['invoices'][$key])) { + if(isset($input['invoices'][$key]['invoice_id'])) { + // if (array_key_exists('invoice_id', $input['invoices'][$key])) { $input['invoices'][$key]['invoice_id'] = $this->decodePrimaryKey($value['invoice_id']); } } diff --git a/app/Http/Requests/Preview/PreviewInvoiceRequest.php b/app/Http/Requests/Preview/PreviewInvoiceRequest.php index 57bd0cf22e..7bbdaebdbe 100644 --- a/app/Http/Requests/Preview/PreviewInvoiceRequest.php +++ b/app/Http/Requests/Preview/PreviewInvoiceRequest.php @@ -11,19 +11,19 @@ namespace App\Http\Requests\Preview; -use App\Models\Quote; +use App\Http\Requests\Request; use App\Models\Client; use App\Models\Credit; +use App\Models\CreditInvitation; use App\Models\Invoice; -use App\Http\Requests\Request; +use App\Models\InvoiceInvitation; +use App\Models\Quote; use App\Models\QuoteInvitation; +use App\Models\RecurringInvoice; +use App\Models\RecurringInvoiceInvitation; +use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; use Illuminate\Validation\Rule; -use App\Models\CreditInvitation; -use App\Models\RecurringInvoice; -use App\Models\InvoiceInvitation; -use App\Utils\Traits\CleanLineItems; -use App\Models\RecurringInvoiceInvitation; class PreviewInvoiceRequest extends Request { @@ -55,7 +55,7 @@ class PreviewInvoiceRequest extends Request return [ 'number' => 'nullable', 'entity' => 'bail|sometimes|in:invoice,quote,credit,recurring_invoice', - 'entity_id' => ['bail','sometimes','integer',Rule::exists($this->entity_plural, 'id')->where('is_deleted',0)->where('company_id', $user->company()->id)], + 'entity_id' => ['bail','sometimes','integer',Rule::exists($this->entity_plural, 'id')->where('is_deleted', 0)->where('company_id', $user->company()->id)], 'client_id' => ['required', Rule::exists(Client::class, 'id')->where('is_deleted', 0)->where('company_id', $user->company()->id)], ]; @@ -76,8 +76,9 @@ class PreviewInvoiceRequest extends Request $input['balance'] = 0; $input['number'] = isset($input['number']) ? $input['number'] : ctrans('texts.live_preview').' #'.rand(0, 1000); - if($input['entity_id'] ?? false) + if($input['entity_id'] ?? false) { $input['entity_id'] = $this->decodePrimaryKey($input['entity_id'], true); + } $this->convertEntityPlural($input['entity'] ?? 'invoice'); @@ -88,26 +89,29 @@ class PreviewInvoiceRequest extends Request { $invitation = false; - if(! $this->entity_id ?? false) + if(! $this->entity_id ?? false) { return $this->stubInvitation(); + } - match($this->entity){ - 'invoice' => $invitation = InvoiceInvitation::withTrashed()->where('invoice_id', $this->entity_id)->first(), - 'quote' => $invitation = QuoteInvitation::withTrashed()->where('quote_id', $this->entity_id)->first(), - 'credit' => $invitation = CreditInvitation::withTrashed()->where('credit_id', $this->entity_id)->first(), - 'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->where('recurring_invoice_id', $this->entity_id)->first(), + match($this->entity) { + 'invoice' => $invitation = InvoiceInvitation::withTrashed()->where('invoice_id', $this->entity_id)->first(), + 'quote' => $invitation = QuoteInvitation::withTrashed()->where('quote_id', $this->entity_id)->first(), + 'credit' => $invitation = CreditInvitation::withTrashed()->where('credit_id', $this->entity_id)->first(), + 'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->where('recurring_invoice_id', $this->entity_id)->first(), }; - if($invitation) + if($invitation) { return $invitation; + } - $invitation = $this->stubInvitation(); + return $this->stubInvitation(); } public function getClient(): ?Client { - if(!$this->client) + if(!$this->client) { $this->client = Client::query()->with('contacts', 'company', 'user')->withTrashed()->find($this->client_id); + } return $this->client; } @@ -147,7 +151,7 @@ class PreviewInvoiceRequest extends Request { $entity = false; - match($this->entity){ + match($this->entity) { 'invoice' => $entity = Invoice::factory()->make(['client_id' => $client->id,'user_id' => $client->user_id, 'company_id' => $client->company_id]), 'quote' => $entity = Quote::factory()->make(['client_id' => $client->id,'user_id' => $client->user_id, 'company_id' => $client->company_id]), 'credit' => $entity = Credit::factory()->make(['client_id' => $client->id,'user_id' => $client->user_id, 'company_id' => $client->company_id]), diff --git a/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php b/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php index 927937bf25..e7075e1a0b 100644 --- a/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php +++ b/app/Http/Requests/Preview/PreviewPurchaseOrderRequest.php @@ -11,15 +11,21 @@ namespace App\Http\Requests\Preview; +use App\Models\Vendor; +use App\Models\PurchaseOrder; use App\Http\Requests\Request; -use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\MakesHash; +use App\Utils\Traits\CleanLineItems; +use App\Models\PurchaseOrderInvitation; class PreviewPurchaseOrderRequest extends Request { use MakesHash; use CleanLineItems; + private ?Vendor $vendor = null; + private string $entity_plural = ''; + /** * Determine if the user is authorized to make this request. * @@ -27,7 +33,10 @@ class PreviewPurchaseOrderRequest extends Request */ public function authorize() : bool { - return auth()->user()->hasIntersectPermissionsOrAdmin(['create_purchase_order', 'edit_purchase_order', 'view_purchase_order']); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->hasIntersectPermissionsOrAdmin(['create_purchase_order', 'edit_purchase_order', 'view_purchase_order']); } public function rules() @@ -52,4 +61,77 @@ class PreviewPurchaseOrderRequest extends Request $this->replace($input); } + + + + public function resolveInvitation() + { + $invitation = false; + + if(! $this->entity_id ?? false) { + return $this->stubInvitation(); + } + + $invitation = PurchaseOrderInvitation::withTrashed()->where('purchase_order_id', $this->entity_id)->first(); + + if($invitation) { + return $invitation; + } + + return $this->stubInvitation(); + + + } + + public function getVendor(): ?Vendor + { + if(!$this->vendor) { + $this->vendor = Vendor::query()->with('contacts', 'company', 'user')->withTrashed()->find($this->vendor_id); + } + + return $this->vendor; + } + + public function setVendor(Vendor $vendor): self + { + $this->vendor = $vendor; + + return $this; + } + + public function stubInvitation() + { + $vendor = Vendor::query()->with('contacts', 'company', 'user')->withTrashed()->find($this->vendor_id); + $this->setVendor($vendor); + $invitation = false; + + $entity = $this->stubEntity($vendor); + $invitation = PurchaseOrderInvitation::factory()->make(); + $invitation->setRelation('purchase_order', $entity); + $invitation->setRelation('contact', $vendor->contacts->first()->load('vendor.company')); + $invitation->setRelation('company', $vendor->company); + + return $invitation; + } + + private function stubEntity(Vendor $vendor) + { + $entity = PurchaseOrder::factory()->make(['vendor_id' => $vendor->id,'user_id' => $vendor->user_id, 'company_id' => $vendor->company_id]); + + $entity->setRelation('vendor', $vendor); + $entity->setRelation('company', $vendor->company); + $entity->setRelation('user', $vendor->user); + $entity->fill($this->all()); + + return $entity; + } + + private function convertEntityPlural(string $entity) :self + { + + $this->entity_plural = 'purchase_orders'; + + return $this; + } + } diff --git a/app/Http/Requests/Project/StoreProjectRequest.php b/app/Http/Requests/Project/StoreProjectRequest.php index 98664cd84c..a8684c0d24 100644 --- a/app/Http/Requests/Project/StoreProjectRequest.php +++ b/app/Http/Requests/Project/StoreProjectRequest.php @@ -28,18 +28,25 @@ class StoreProjectRequest extends Request */ public function authorize() : bool { - return auth()->user()->can('create', Project::class); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->can('create', Project::class); } public function rules() { + + /** @var \App\Models\User $user */ + $user = auth()->user(); + $rules = []; $rules['name'] = 'required'; - $rules['client_id'] = 'required|exists:clients,id,company_id,'.auth()->user()->company()->id; + $rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id; if (isset($this->number)) { - $rules['number'] = Rule::unique('projects')->where('company_id', auth()->user()->company()->id); + $rules['number'] = Rule::unique('projects')->where('company_id', $user->company()->id); } if ($this->file('documents') && is_array($this->file('documents'))) { diff --git a/app/Http/Requests/Project/UpdateProjectRequest.php b/app/Http/Requests/Project/UpdateProjectRequest.php index 484f18f036..dc5484f8a2 100644 --- a/app/Http/Requests/Project/UpdateProjectRequest.php +++ b/app/Http/Requests/Project/UpdateProjectRequest.php @@ -26,15 +26,23 @@ class UpdateProjectRequest extends Request */ public function authorize() : bool { - return auth()->user()->can('edit', $this->project); + + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->can('edit', $this->project); } public function rules() { + + /** @var \App\Models\User $user */ + $user = auth()->user(); + $rules = []; if (isset($this->number)) { - $rules['number'] = Rule::unique('projects')->where('company_id', auth()->user()->company()->id)->ignore($this->project->id); + $rules['number'] = Rule::unique('projects')->where('company_id', $user->company()->id)->ignore($this->project->id); } if ($this->file('documents') && is_array($this->file('documents'))) { diff --git a/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php b/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php index 746e17abf1..8d290a696a 100644 --- a/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php +++ b/app/Http/Requests/PurchaseOrder/UploadPurchaseOrderRequest.php @@ -44,7 +44,7 @@ class UploadPurchaseOrderRequest extends Request $rules['file'] = $this->file_validation; } - $rules['is_public'] = 'sometimes|boolean'; + $rules['is_public'] = 'sometimes|boolean'; return $rules; } diff --git a/app/Http/Requests/Quote/BulkActionQuoteRequest.php b/app/Http/Requests/Quote/BulkActionQuoteRequest.php index c9f41313a5..cb77becc06 100644 --- a/app/Http/Requests/Quote/BulkActionQuoteRequest.php +++ b/app/Http/Requests/Quote/BulkActionQuoteRequest.php @@ -34,7 +34,7 @@ class BulkActionQuoteRequest extends Request 'action' => 'sometimes|in:convert_to_invoice,convert_to_project,email,bulk_download,bulk_print,clone_to_invoice,approve,download,restore,archive,delete,send_email,mark_sent', ]; - if (in_array($input['action'], ['convert,convert_to_invoice']) ) { + if (in_array($input['action'], ['convert,convert_to_invoice'])) { $rules['action'] = [new ConvertableQuoteRule()]; } diff --git a/app/Http/Requests/Statements/CreateStatementRequest.php b/app/Http/Requests/Statements/CreateStatementRequest.php index 3406be9468..2cf38a3a58 100644 --- a/app/Http/Requests/Statements/CreateStatementRequest.php +++ b/app/Http/Requests/Statements/CreateStatementRequest.php @@ -17,9 +17,10 @@ class CreateStatementRequest extends Request */ public function authorize(): bool { - // return auth()->user()->isAdmin(); + /** @var \App\Models\User $user */ + $user = auth()->user(); - return auth()->user()->can('view', $this->client()); + return $user->can('view', $this->client()); } /** @@ -29,14 +30,18 @@ class CreateStatementRequest extends Request */ public function rules() { + /** @var \App\Models\User $user */ + $user = auth()->user(); + return [ 'start_date' => 'required|date_format:Y-m-d', 'end_date' => 'required|date_format:Y-m-d', - 'client_id' => 'bail|required|exists:clients,id,company_id,'.auth()->user()->company()->id, + 'client_id' => 'bail|required|exists:clients,id,company_id,'.$user->company()->id, 'show_payments_table' => 'boolean', 'show_aging_table' => 'boolean', 'show_credits_table' => 'boolean', 'status' => 'string', + 'template' => 'sometimes|string|nullable', ]; } diff --git a/app/Http/Requests/Task/StoreTaskRequest.php b/app/Http/Requests/Task/StoreTaskRequest.php index 52d331d3ab..5ae5e13dd4 100644 --- a/app/Http/Requests/Task/StoreTaskRequest.php +++ b/app/Http/Requests/Task/StoreTaskRequest.php @@ -54,15 +54,24 @@ class StoreTaskRequest extends Request $rules['project_id'] = 'bail|required|exists:projects,id,company_id,'.$user->company()->id.',is_deleted,0'; } - $rules['timelog'] = ['bail','array',function ($attribute, $values, $fail) { + $rules['time_log'] = ['bail', function ($attribute, $values, $fail) { + + if(is_string($values)) { + $values = json_decode($values, 1); + } + + if(!is_array($values)) { + return $fail('The '.$attribute.' is invalid. Must be an array.'); + } + foreach ($values as $k) { if (!is_int($k[0]) || !is_int($k[1])) { - $fail('The '.$attribute.' - '.print_r($k, 1).' is invalid. Unix timestamps only.'); + return $fail('The '.$attribute.' - '.print_r($k, 1).' is invalid. Unix timestamps only.'); } } if (!$this->checkTimeLog($values)) { - $fail('Please correct overlapping values'); + return $fail('Please correct overlapping values'); } }]; diff --git a/app/Http/Requests/Task/UpdateTaskRequest.php b/app/Http/Requests/Task/UpdateTaskRequest.php index 7107df9fe6..7779dc0340 100644 --- a/app/Http/Requests/Task/UpdateTaskRequest.php +++ b/app/Http/Requests/Task/UpdateTaskRequest.php @@ -34,35 +34,51 @@ class UpdateTaskRequest extends Request if ($this->task->invoice_id && $this->task->company->invoice_task_lock) { return false; } + + /** @var \App\Models\User $user */ + $user = auth()->user(); - return auth()->user()->can('edit', $this->task); + return $user->can('edit', $this->task); } public function rules() { + + /** @var \App\Models\User $user */ + $user = auth()->user(); + $rules = []; if (isset($this->number)) { - $rules['number'] = Rule::unique('tasks')->where('company_id', auth()->user()->company()->id)->ignore($this->task->id); + $rules['number'] = Rule::unique('tasks')->where('company_id', $user->company()->id)->ignore($this->task->id); } if (isset($this->client_id)) { - $rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.auth()->user()->company()->id.',is_deleted,0'; + $rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0'; } if (isset($this->project_id)) { - $rules['project_id'] = 'bail|required|exists:projects,id,company_id,'.auth()->user()->company()->id.',is_deleted,0'; + $rules['project_id'] = 'bail|required|exists:projects,id,company_id,'.$user->company()->id.',is_deleted,0'; } - $rules['timelog'] = ['bail','array',function ($attribute, $values, $fail) { + $rules['time_log'] = ['bail',function ($attribute, $values, $fail) { + + if(is_string($values)) { + $values = json_decode($values, 1); + } + + if(!is_array($values)) { + return $fail('The '.$attribute.' is invalid. Must be an array.'); + } + foreach ($values as $k) { if (!is_int($k[0]) || !is_int($k[1])) { - $fail('The '.$attribute.' - '.print_r($k, 1).' is invalid. Unix timestamps only.'); + return $fail('The '.$attribute.' - '.print_r($k, 1).' is invalid. Unix timestamps only.'); } } if (!$this->checkTimeLog($values)) { - $fail('Please correct overlapping values'); + return $fail('Please correct overlapping values'); } }]; @@ -104,10 +120,10 @@ class UpdateTaskRequest extends Request $input['color'] = ''; } - if(isset($input['project_id']) && isset($input['client_id'])){ + if(isset($input['project_id']) && isset($input['client_id'])) { $search_project_with_client = Project::withTrashed()->where('id', $input['project_id'])->where('client_id', $input['client_id'])->company()->doesntExist(); - if($search_project_with_client){ + if($search_project_with_client) { unset($input['project_id']); } diff --git a/app/Http/Requests/Task/UploadTaskRequest.php b/app/Http/Requests/Task/UploadTaskRequest.php index 6b7d96ef04..088ec573c3 100644 --- a/app/Http/Requests/Task/UploadTaskRequest.php +++ b/app/Http/Requests/Task/UploadTaskRequest.php @@ -53,8 +53,9 @@ class UploadTaskRequest extends Request { $input = $this->all(); - if(isset($input['is_public'])) + if(isset($input['is_public'])) { $input['is_public'] = $this->toBoolean($input['is_public']); + } $this->replace($input); } diff --git a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php index c0fc0c9d60..312e073099 100644 --- a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php @@ -14,7 +14,6 @@ namespace App\Http\Requests\TaskScheduler; use App\Http\Requests\Request; use App\Http\ValidationRules\Scheduler\ValidClientIds; use App\Utils\Traits\MakesHash; -use Illuminate\Validation\Rule; class StoreSchedulerRequest extends Request { @@ -60,7 +59,7 @@ class StoreSchedulerRequest extends Request $input['next_run_client'] = $input['next_run']; } - if($input['template'] == 'email_record'){ + if($input['template'] == 'email_record') { $input['frequency_id'] = 0; } diff --git a/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php b/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php index 24dea23f0a..6a7750320f 100644 --- a/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php @@ -12,7 +12,6 @@ namespace App\Http\Requests\TaskScheduler; use App\Http\Requests\Request; use App\Http\ValidationRules\Scheduler\ValidClientIds; -use Illuminate\Validation\Rule; class UpdateSchedulerRequest extends Request { diff --git a/app/Http/Requests/TaskStatus/UpdateTaskStatusRequest.php b/app/Http/Requests/TaskStatus/UpdateTaskStatusRequest.php index e7a0b757c9..c1f2bb31ae 100644 --- a/app/Http/Requests/TaskStatus/UpdateTaskStatusRequest.php +++ b/app/Http/Requests/TaskStatus/UpdateTaskStatusRequest.php @@ -13,7 +13,6 @@ namespace App\Http\Requests\TaskStatus; use App\Http\Requests\Request; use App\Utils\Traits\MakesHash; -use Illuminate\Validation\Rule; class UpdateTaskStatusRequest extends Request { diff --git a/app/Http/Requests/User/BulkUserRequest.php b/app/Http/Requests/User/BulkUserRequest.php index c07032f4f2..f0893654e5 100644 --- a/app/Http/Requests/User/BulkUserRequest.php +++ b/app/Http/Requests/User/BulkUserRequest.php @@ -11,10 +11,10 @@ namespace App\Http\Requests\User; -use App\Utils\Ninja; use App\Http\Requests\Request; -use Illuminate\Auth\Access\AuthorizationException; use App\Http\ValidationRules\Ninja\CanRestoreUserRule; +use App\Utils\Ninja; +use Illuminate\Auth\Access\AuthorizationException; class BulkUserRequest extends Request { @@ -25,8 +25,9 @@ class BulkUserRequest extends Request */ public function authorize() : bool { - if($this->action == 'delete' && in_array(auth()->user()->hashed_id, $this->ids)) + if($this->action == 'delete' && in_array(auth()->user()->hashed_id, $this->ids)) { return false; + } return auth()->user()->isAdmin(); } diff --git a/app/Http/Requests/User/DisconnectUserMailerRequest.php b/app/Http/Requests/User/DisconnectUserMailerRequest.php index 881276e4dc..ffe07871e8 100644 --- a/app/Http/Requests/User/DisconnectUserMailerRequest.php +++ b/app/Http/Requests/User/DisconnectUserMailerRequest.php @@ -23,7 +23,7 @@ class DisconnectUserMailerRequest extends Request * @return bool */ public function authorize() : bool - { + { return auth()->user()->id == $this->user->id || auth()->user()->isAdmin(); } diff --git a/app/Http/Requests/Vendor/StoreVendorRequest.php b/app/Http/Requests/Vendor/StoreVendorRequest.php index 3ce8ba4721..f60c7997b7 100644 --- a/app/Http/Requests/Vendor/StoreVendorRequest.php +++ b/app/Http/Requests/Vendor/StoreVendorRequest.php @@ -38,8 +38,21 @@ class StoreVendorRequest extends Request $user = auth()->user(); $rules = []; - + + $rules['contacts'] = 'bail|array'; $rules['contacts.*.email'] = 'bail|nullable|distinct|sometimes|email'; + $rules['contacts.*.password'] = [ + 'bail', + 'nullable', + 'sometimes', + 'string', + 'min:7', // must be at least 10 characters in length + 'regex:/[a-z]/', // must contain at least one lowercase letter + 'regex:/[A-Z]/', // must contain at least one uppercase letter + 'regex:/[0-9]/', // must contain at least one digit + //'regex:/[@$!%*#?&.]/', // must contain a special character + ]; + if (isset($this->number)) { $rules['number'] = Rule::unique('vendors')->where('company_id', $user->company()->id); diff --git a/app/Http/Requests/Vendor/UpdateVendorRequest.php b/app/Http/Requests/Vendor/UpdateVendorRequest.php index b50e8cf792..e8b6811fd1 100644 --- a/app/Http/Requests/Vendor/UpdateVendorRequest.php +++ b/app/Http/Requests/Vendor/UpdateVendorRequest.php @@ -45,7 +45,20 @@ class UpdateVendorRequest extends Request $rules['number'] = Rule::unique('vendors')->where('company_id', $user->company()->id)->ignore($this->vendor->id); } - $rules['contacts.*.email'] = 'nullable|distinct'; + $rules['contacts'] = 'bail|array'; + $rules['contacts.*.email'] = 'bail|nullable|distinct|sometimes|email'; + $rules['contacts.*.password'] = [ + 'bail', + 'nullable', + 'sometimes', + 'string', + 'min:7', // must be at least 10 characters in length + 'regex:/[a-z]/', // must contain at least one lowercase letter + 'regex:/[A-Z]/', // must contain at least one uppercase letter + 'regex:/[0-9]/', // must contain at least one digit + //'regex:/[@$!%*#?&.]/', // must contain a special character + ]; + $rules['currency_id'] = 'bail|sometimes|exists:currencies,id'; if ($this->file('documents') && is_array($this->file('documents'))) { diff --git a/app/Http/Requests/Vendor/UploadVendorRequest.php b/app/Http/Requests/Vendor/UploadVendorRequest.php index a9263fb979..f1219bd6d6 100644 --- a/app/Http/Requests/Vendor/UploadVendorRequest.php +++ b/app/Http/Requests/Vendor/UploadVendorRequest.php @@ -50,8 +50,9 @@ class UploadVendorRequest extends Request { $input = $this->all(); - if(isset($input['is_public'])) + if(isset($input['is_public'])) { $input['is_public'] = $this->toBoolean($input['is_public']); + } $this->replace($input); } diff --git a/app/Http/Requests/Webhook/UpdateWebhookRequest.php b/app/Http/Requests/Webhook/UpdateWebhookRequest.php index d8fd2ed783..a02890d55d 100644 --- a/app/Http/Requests/Webhook/UpdateWebhookRequest.php +++ b/app/Http/Requests/Webhook/UpdateWebhookRequest.php @@ -49,7 +49,7 @@ class UpdateWebhookRequest extends Request } // if(isset($input['headers']) && count($input['headers']) == 0) - // $input['headers'] = null; + // $input['headers'] = null; $this->replace($input); } diff --git a/app/Http/ValidationRules/Credit/ValidCreditsRules.php b/app/Http/ValidationRules/Credit/ValidCreditsRules.php index d02097df21..8c43fed216 100644 --- a/app/Http/ValidationRules/Credit/ValidCreditsRules.php +++ b/app/Http/ValidationRules/Credit/ValidCreditsRules.php @@ -76,7 +76,7 @@ class ValidCreditsRules implements Rule return false; } - if($cred->status_id == Credit::STATUS_DRAFT){ + if($cred->status_id == Credit::STATUS_DRAFT) { $cred->service()->markSent()->save(); $cred = $cred->fresh(); } diff --git a/app/Http/ValidationRules/Payment/ValidRefundableRequest.php b/app/Http/ValidationRules/Payment/ValidRefundableRequest.php index 6de59ca0b9..49530bca72 100644 --- a/app/Http/ValidationRules/Payment/ValidRefundableRequest.php +++ b/app/Http/ValidationRules/Payment/ValidRefundableRequest.php @@ -11,7 +11,6 @@ namespace App\Http\ValidationRules\Payment; -use App\Models\Credit; use App\Models\Invoice; use App\Models\Payment; use App\Utils\Traits\MakesHash; diff --git a/app/Http/ValidationRules/PaymentAppliedValidAmount.php b/app/Http/ValidationRules/PaymentAppliedValidAmount.php index 2958f04229..f64f72d2b1 100644 --- a/app/Http/ValidationRules/PaymentAppliedValidAmount.php +++ b/app/Http/ValidationRules/PaymentAppliedValidAmount.php @@ -91,7 +91,7 @@ class PaymentAppliedValidAmount implements Rule } } - if(count($this->input['invoices']) >=1 && $payment->status_id == Payment::STATUS_PENDING){ + if(count($this->input['invoices']) >=1 && $payment->status_id == Payment::STATUS_PENDING) { $this->message = 'Cannot apply a payment until the status is completed.'; return false; } diff --git a/app/Http/ValidationRules/Project/ValidProjectForClient.php b/app/Http/ValidationRules/Project/ValidProjectForClient.php index 46f3b1a8c8..188d94c939 100644 --- a/app/Http/ValidationRules/Project/ValidProjectForClient.php +++ b/app/Http/ValidationRules/Project/ValidProjectForClient.php @@ -53,7 +53,7 @@ class ValidProjectForClient implements Rule return; } - if(!isset($this->input['client_id'])){ + if(!isset($this->input['client_id'])) { $this->message = 'No Client ID provided.'; return false; } diff --git a/app/Http/ValidationRules/ValidAmount.php b/app/Http/ValidationRules/ValidAmount.php index 4438b935ad..2f219f17b8 100644 --- a/app/Http/ValidationRules/ValidAmount.php +++ b/app/Http/ValidationRules/ValidAmount.php @@ -27,7 +27,7 @@ class ValidAmount implements Rule { return is_numeric((string) $value); //return filter_var((string)$value, FILTER_VALIDATE_FLOAT); -// return preg_match('^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$^', (string)$value); + // return preg_match('^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$^', (string)$value); // return trim($value, '-1234567890.,') === ''; } diff --git a/app/Import/Definitions/VendorMap.php b/app/Import/Definitions/VendorMap.php index 4e5cbd3752..1c23f5e340 100644 --- a/app/Import/Definitions/VendorMap.php +++ b/app/Import/Definitions/VendorMap.php @@ -33,14 +33,18 @@ class VendorMap 14 => 'vendor.state', 15 => 'vendor.postal_code', 16 => 'vendor.country_id', - 17 => 'contact.first_name', - 18 => 'contact.last_name', - 19 => 'contact.email', - 20 => 'contact.phone', - 21 => 'contact.custom_value1', - 22 => 'contact.custom_value2', - 23 => 'contact.custom_value3', - 24 => 'contact.custom_value4', + 17 => 'vendor.custom_value1', + 18 => 'vendor.custom_value2', + 19 => 'vendor.custom_value3', + 20 => 'vendor.custom_value4', + 21 => 'contact.first_name', + 22 => 'contact.last_name', + 23 => 'contact.email', + 24 => 'contact.phone', + 25 => 'contact.custom_value1', + 26 => 'contact.custom_value2', + 27 => 'contact.custom_value3', + 28 => 'contact.custom_value4', ]; } @@ -65,14 +69,18 @@ class VendorMap 14 => 'texts.state', 15 => 'texts.postal_code', 16 => 'texts.country', - 17 => 'texts.first_name', - 18 => 'texts.last_name', - 19 => 'texts.email', - 20 => 'texts.phone', - 21 => 'texts.custom_value', - 22 => 'texts.custom_value', - 23 => 'texts.custom_value', - 24 => 'texts.custom_value', + 17 => 'texts.custom_value', + 18 => 'texts.custom_value', + 19 => 'texts.custom_value', + 20 => 'texts.custom_value', + 21 => 'texts.first_name', + 22 => 'texts.last_name', + 23 => 'texts.email', + 24 => 'texts.phone', + 25 => 'texts.custom_value', + 26 => 'texts.custom_value', + 27 => 'texts.custom_value', + 28 => 'texts.custom_value', ]; } } diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index e401e85aa0..f5396e7efd 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -11,31 +11,31 @@ namespace App\Import\Providers; -use App\Models\User; -use App\Models\Quote; -use League\Csv\Reader; -use App\Models\Company; -use App\Models\Invoice; -use League\Csv\Statement; -use App\Factory\QuoteFactory; use App\Factory\ClientFactory; -use Illuminate\Support\Carbon; use App\Factory\InvoiceFactory; use App\Factory\PaymentFactory; +use App\Factory\QuoteFactory; +use App\Factory\RecurringInvoiceFactory; +use App\Http\Requests\Quote\StoreQuoteRequest; use App\Import\ImportException; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; -use App\Utils\Traits\CleanLineItems; -use App\Repositories\QuoteRepository; -use Illuminate\Support\Facades\Cache; -use App\Repositories\ClientRepository; use App\Mail\Import\CsvImportCompleted; +use App\Models\Company; +use App\Models\Invoice; +use App\Models\Quote; +use App\Models\User; +use App\Repositories\ClientRepository; use App\Repositories\InvoiceRepository; use App\Repositories\PaymentRepository; -use App\Factory\RecurringInvoiceFactory; -use Illuminate\Support\Facades\Validator; -use App\Http\Requests\Quote\StoreQuoteRequest; +use App\Repositories\QuoteRepository; use App\Repositories\RecurringInvoiceRepository; +use App\Utils\Traits\CleanLineItems; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Validator; +use League\Csv\Reader; +use League\Csv\Statement; class BaseImport { @@ -482,8 +482,9 @@ class BaseImport nlog($invoice_data); $saveable_invoice_data = $invoice_data; - if(array_key_exists('payments', $saveable_invoice_data)) + if(array_key_exists('payments', $saveable_invoice_data)) { unset($saveable_invoice_data['payments']); + } $invoice_repository->save($saveable_invoice_data, $invoice); @@ -524,8 +525,7 @@ class BaseImport $payment_date = Carbon::parse($payment->date); - if(!$payment_date->isToday()) - { + if(!$payment_date->isToday()) { $payment->paymentables()->update(['created_at' => $payment_date]); @@ -743,8 +743,9 @@ class BaseImport } - if($user) + if($user) { return $user->id; + } $user = User::whereRaw("account_id = ? AND CONCAT_WS(' ', first_name, last_name) like ?", [$this->company->account_id, '%'.$user_hash.'%']) ->first(); diff --git a/app/Import/Providers/Csv.php b/app/Import/Providers/Csv.php index 8615328203..9e29d5af9f 100644 --- a/app/Import/Providers/Csv.php +++ b/app/Import/Providers/Csv.php @@ -11,44 +11,44 @@ namespace App\Import\Providers; -use App\Factory\QuoteFactory; +use App\Factory\BankTransactionFactory; use App\Factory\ClientFactory; -use App\Factory\VendorFactory; use App\Factory\ExpenseFactory; use App\Factory\InvoiceFactory; use App\Factory\PaymentFactory; use App\Factory\ProductFactory; -use App\Utils\Traits\MakesHash; -use App\Repositories\QuoteRepository; -use App\Repositories\ClientRepository; -use App\Repositories\VendorRepository; -use App\Factory\BankTransactionFactory; -use App\Repositories\ExpenseRepository; -use App\Repositories\InvoiceRepository; -use App\Repositories\PaymentRepository; -use App\Repositories\ProductRepository; +use App\Factory\QuoteFactory; use App\Factory\RecurringInvoiceFactory; -use App\Services\Bank\BankMatchingService; -use App\Http\Requests\Quote\StoreQuoteRequest; -use App\Repositories\BankTransactionRepository; +use App\Factory\VendorFactory; +use App\Http\Requests\BankTransaction\StoreBankTransactionRequest; use App\Http\Requests\Client\StoreClientRequest; -use App\Http\Requests\Vendor\StoreVendorRequest; -use App\Import\Transformer\Bank\BankTransformer; -use App\Import\Transformer\Csv\QuoteTransformer; -use App\Repositories\RecurringInvoiceRepository; -use App\Import\Transformer\Csv\ClientTransformer; -use App\Import\Transformer\Csv\VendorTransformer; use App\Http\Requests\Expense\StoreExpenseRequest; use App\Http\Requests\Invoice\StoreInvoiceRequest; use App\Http\Requests\Payment\StorePaymentRequest; use App\Http\Requests\Product\StoreProductRequest; +use App\Http\Requests\Quote\StoreQuoteRequest; +use App\Http\Requests\RecurringInvoice\StoreRecurringInvoiceRequest; +use App\Http\Requests\Vendor\StoreVendorRequest; +use App\Import\Transformer\Bank\BankTransformer; +use App\Import\Transformer\Csv\ClientTransformer; use App\Import\Transformer\Csv\ExpenseTransformer; use App\Import\Transformer\Csv\InvoiceTransformer; use App\Import\Transformer\Csv\PaymentTransformer; use App\Import\Transformer\Csv\ProductTransformer; +use App\Import\Transformer\Csv\QuoteTransformer; use App\Import\Transformer\Csv\RecurringInvoiceTransformer; -use App\Http\Requests\BankTransaction\StoreBankTransactionRequest; -use App\Http\Requests\RecurringInvoice\StoreRecurringInvoiceRequest; +use App\Import\Transformer\Csv\VendorTransformer; +use App\Repositories\BankTransactionRepository; +use App\Repositories\ClientRepository; +use App\Repositories\ExpenseRepository; +use App\Repositories\InvoiceRepository; +use App\Repositories\PaymentRepository; +use App\Repositories\ProductRepository; +use App\Repositories\QuoteRepository; +use App\Repositories\RecurringInvoiceRepository; +use App\Repositories\VendorRepository; +use App\Services\Bank\BankMatchingService; +use App\Utils\Traits\MakesHash; class Csv extends BaseImport implements ImportInterface { diff --git a/app/Import/Transformer/BaseTransformer.php b/app/Import/Transformer/BaseTransformer.php index f651e164aa..31c05ceb16 100644 --- a/app/Import/Transformer/BaseTransformer.php +++ b/app/Import/Transformer/BaseTransformer.php @@ -11,27 +11,27 @@ namespace App\Import\Transformer; -use App\Models\Quote; -use App\Utils\Number; +use App\Factory\ClientFactory; +use App\Factory\ExpenseCategoryFactory; +use App\Factory\ProjectFactory; +use App\Factory\VendorFactory; use App\Models\Client; -use App\Models\Vendor; +use App\Models\ClientContact; use App\Models\Country; use App\Models\Expense; +use App\Models\ExpenseCategory; use App\Models\Invoice; +use App\Models\PaymentType; use App\Models\Product; use App\Models\Project; -use App\Models\TaxRate; -use App\Models\PaymentType; -use App\Models\ClientContact; -use App\Factory\ClientFactory; -use App\Factory\VendorFactory; -use Illuminate\Support\Carbon; -use App\Factory\ProjectFactory; -use App\Models\ExpenseCategory; +use App\Models\Quote; use App\Models\RecurringInvoice; -use Illuminate\Support\Facades\Cache; +use App\Models\TaxRate; +use App\Models\Vendor; use App\Repositories\ClientRepository; -use App\Factory\ExpenseCategoryFactory; +use App\Utils\Number; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Cache; /** * Class BaseTransformer. @@ -47,8 +47,9 @@ class BaseTransformer public function parseDate($date) { - if(stripos($date,"/") !== false && $this->company->settings->country_id != 840) + if(stripos($date, "/") !== false && $this->company->settings->country_id != 840) { $date = str_replace('/', '-', $date); + } try { $parsed_date = Carbon::parse($date); @@ -331,10 +332,11 @@ class BaseTransformer */ public function getFloatOrOne($data, $field) { - if (array_key_exists($field, $data)) + if (array_key_exists($field, $data)) { return Number::parseStringFloat($data[$field]) > 0 ? Number::parseStringFloat($data[$field]) : 1; + } - return 1; + return 1; } @@ -637,8 +639,9 @@ class BaseTransformer ]) ->first(); - if($ec) + if($ec) { return $ec->id; + } $ec = \App\Factory\ExpenseCategoryFactory::create($this->company->id, $this->company->owner()->id); $ec->name = $name; diff --git a/app/Import/Transformer/Csv/InvoiceTransformer.php b/app/Import/Transformer/Csv/InvoiceTransformer.php index 1399990a2a..38980311ea 100644 --- a/app/Import/Transformer/Csv/InvoiceTransformer.php +++ b/app/Import/Transformer/Csv/InvoiceTransformer.php @@ -167,7 +167,7 @@ class InvoiceTransformer extends BaseTransformer ), ], ]; - } + } // elseif ( // isset($transformed['amount']) && // isset($transformed['balance']) && diff --git a/app/Import/Transformer/Csv/RecurringInvoiceTransformer.php b/app/Import/Transformer/Csv/RecurringInvoiceTransformer.php index d4c2a17bdf..2f924da831 100644 --- a/app/Import/Transformer/Csv/RecurringInvoiceTransformer.php +++ b/app/Import/Transformer/Csv/RecurringInvoiceTransformer.php @@ -11,10 +11,10 @@ namespace App\Import\Transformer\Csv; -use App\Models\Invoice; use App\Import\ImportException; -use App\Models\RecurringInvoice; use App\Import\Transformer\BaseTransformer; +use App\Models\Invoice; +use App\Models\RecurringInvoice; /** * Class RecurringInvoiceTransformer. @@ -134,10 +134,12 @@ class RecurringInvoiceTransformer extends BaseTransformer // ] ?? Invoice::STATUS_SENT, 'auto_bill' => $this->getAutoBillFlag( $this->getString($invoice_data, 'invoice.auto_bill') - ), - 'frequency_id' => $this->getFrequency(isset($invoice_data['invoice.frequency_id']) ? $invoice_data['invoice.frequency_id'] : 'monthly' ), - 'remaining_cycles' => $this->getRemainingCycles(isset($invoice_data['invoice.remaining_cycles']) ? $invoice_data['invoice.remaining_cycles'] : -1 + 'frequency_id' => $this->getFrequency( + isset($invoice_data['invoice.frequency_id']) ? $invoice_data['invoice.frequency_id'] : 'monthly' + ), + 'remaining_cycles' => $this->getRemainingCycles( + isset($invoice_data['invoice.remaining_cycles']) ? $invoice_data['invoice.remaining_cycles'] : -1 ), // 'archived' => $status === 'archived', ]; diff --git a/app/Import/Transformer/Invoice2Go/InvoiceTransformer.php b/app/Import/Transformer/Invoice2Go/InvoiceTransformer.php index ce790aa254..e6ad42416a 100644 --- a/app/Import/Transformer/Invoice2Go/InvoiceTransformer.php +++ b/app/Import/Transformer/Invoice2Go/InvoiceTransformer.php @@ -63,8 +63,7 @@ class InvoiceTransformer extends BaseTransformer $client_id = null; - if($this->hasClient($this->getString($invoice_data, 'Name') || $this->getContact($this->getString($invoice_data, 'EmailRecipient')))) - { + if($this->hasClient($this->getString($invoice_data, 'Name') || $this->getContact($this->getString($invoice_data, 'EmailRecipient')))) { $client_id = $this->getClient($this->getString($invoice_data, 'Name'), $this->getString($invoice_data, 'EmailRecipient')); diff --git a/app/Import/Transformer/Zoho/ClientTransformer.php b/app/Import/Transformer/Zoho/ClientTransformer.php index 0849641498..b63891b5b3 100644 --- a/app/Import/Transformer/Zoho/ClientTransformer.php +++ b/app/Import/Transformer/Zoho/ClientTransformer.php @@ -31,8 +31,7 @@ class ClientTransformer extends BaseTransformer if(isset($data[$client_id_proxy]) && $this->hasClientIdNumber($data[$client_id_proxy])) { throw new ImportException('Client ID already exists => '. $data[$client_id_proxy]); - } - elseif (isset($data['Company Name']) && $this->hasClient($data['Company Name'])) { + } elseif (isset($data['Company Name']) && $this->hasClient($data['Company Name'])) { throw new ImportException('Client already exists => '. $data['Company Name']); } diff --git a/app/Import/Transformer/Zoho/InvoiceTransformer.php b/app/Import/Transformer/Zoho/InvoiceTransformer.php index faae4fffa2..704c82008e 100644 --- a/app/Import/Transformer/Zoho/InvoiceTransformer.php +++ b/app/Import/Transformer/Zoho/InvoiceTransformer.php @@ -141,7 +141,6 @@ class InvoiceTransformer extends BaseTransformer 'postal_code' => $this->getString($invoice_data, 'Billing Code'), 'country_id' => $this->getCountryId($this->getString($invoice_data, 'Billing Country')), ], - \App\Factory\ClientFactory::create( $this->company->id, $this->company->owner()->id diff --git a/app/Jobs/Bank/MatchBankTransactions.php b/app/Jobs/Bank/MatchBankTransactions.php index 518926734c..b0453fb4c7 100644 --- a/app/Jobs/Bank/MatchBankTransactions.php +++ b/app/Jobs/Bank/MatchBankTransactions.php @@ -182,7 +182,7 @@ class MatchBankTransactions implements ShouldQueue return $this; } - private function coalesceExpenses($expense): string + private function coalesceExpenses($expense): string { if (!$this->bt->expense_id || strlen($this->bt->expense_id) < 1) { diff --git a/app/Jobs/Bank/ProcessBankTransactions.php b/app/Jobs/Bank/ProcessBankTransactions.php index d6b6d8582a..2d621799de 100644 --- a/app/Jobs/Bank/ProcessBankTransactions.php +++ b/app/Jobs/Bank/ProcessBankTransactions.php @@ -11,20 +11,20 @@ namespace App\Jobs\Bank; -use App\Models\Company; +use App\Helpers\Bank\Yodlee\Transformer\AccountTransformer; +use App\Helpers\Bank\Yodlee\Yodlee; use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; use App\Models\BankIntegration; use App\Models\BankTransaction; -use App\Helpers\Bank\Yodlee\Yodlee; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; +use App\Models\Company; +use App\Notifications\Ninja\GenericNinjaAdminNotification; use App\Services\Bank\BankMatchingService; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; -use App\Notifications\Ninja\GenericNinjaAdminNotification; -use App\Helpers\Bank\Yodlee\Transformer\AccountTransformer; +use Illuminate\Queue\SerializesModels; class ProcessBankTransactions implements ShouldQueue { @@ -116,8 +116,7 @@ class ProcessBankTransactions implements ShouldQueue } } - } - catch(\Exception $e) { + } catch(\Exception $e) { nlog("YODLEE: unable to update account summary for {$this->bank_integration->bank_account_id} => ". $e->getMessage()); } diff --git a/app/Jobs/Client/CheckVat.php b/app/Jobs/Client/CheckVat.php index 49d5f17d2a..a51a6ce1c0 100644 --- a/app/Jobs/Client/CheckVat.php +++ b/app/Jobs/Client/CheckVat.php @@ -11,18 +11,17 @@ namespace App\Jobs\Client; +use App\Libraries\MultiDB; use App\Models\Client; use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; -use App\DataProviders\USStates; -use App\Utils\Traits\MakesHash; use App\Services\Tax\TaxService; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; +use App\Utils\Traits\MakesHash; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; +use Illuminate\Queue\SerializesModels; class CheckVat implements ShouldQueue { diff --git a/app/Jobs/Client/UpdateTaxData.php b/app/Jobs/Client/UpdateTaxData.php index 89a25bdd86..c27733c066 100644 --- a/app/Jobs/Client/UpdateTaxData.php +++ b/app/Jobs/Client/UpdateTaxData.php @@ -11,18 +11,17 @@ namespace App\Jobs\Client; -use App\DataMapper\Tax\ZipTax\Response; +use App\DataProviders\USStates; +use App\Libraries\MultiDB; use App\Models\Client; use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; -use App\DataProviders\USStates; use App\Utils\Traits\MakesHash; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; +use Illuminate\Queue\SerializesModels; class UpdateTaxData implements ShouldQueue { @@ -52,8 +51,9 @@ class UpdateTaxData implements ShouldQueue { MultiDB::setDb($this->company->db); - if($this->company->account->isFreeHostedClient() || $this->client->country_id != 840) + if($this->company->account->isFreeHostedClient() || $this->client->country_id != 840) { return; + } $tax_provider = new \App\Services\Tax\Providers\TaxProvider($this->company, $this->client); @@ -69,7 +69,7 @@ class UpdateTaxData implements ShouldQueue } - }catch(\Exception $e){ + } catch(\Exception $e) { nlog("problem getting tax data => ".$e->getMessage()); } @@ -87,4 +87,4 @@ class UpdateTaxData implements ShouldQueue } -} \ No newline at end of file +} diff --git a/app/Jobs/Company/CompanyExport.php b/app/Jobs/Company/CompanyExport.php index 1a3bfc43b2..b58e20f26a 100644 --- a/app/Jobs/Company/CompanyExport.php +++ b/app/Jobs/Company/CompanyExport.php @@ -11,30 +11,29 @@ namespace App\Jobs\Company; -use App\Models\User; -use App\Utils\Ninja; -use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Support\Str; -use App\Mail\DownloadBackup; -use App\Jobs\Util\UnlinkFile; -use App\Models\VendorContact; -use Illuminate\Bus\Queueable; -use App\Models\QuoteInvitation; -use App\Utils\Traits\MakesHash; -use App\Models\CreditInvitation; use App\Jobs\Mail\NinjaMailerJob; -use App\Models\InvoiceInvitation; -use Illuminate\Support\Facades\App; use App\Jobs\Mail\NinjaMailerObject; -use Illuminate\Support\Facades\Cache; -use Illuminate\Queue\SerializesModels; +use App\Jobs\Util\UnlinkFile; +use App\Libraries\MultiDB; +use App\Mail\DownloadBackup; +use App\Models\Company; +use App\Models\CreditInvitation; +use App\Models\InvoiceInvitation; use App\Models\PurchaseOrderInvitation; -use Illuminate\Support\Facades\Storage; -use Illuminate\Queue\InteractsWithQueue; +use App\Models\QuoteInvitation; use App\Models\RecurringInvoiceInvitation; +use App\Models\User; +use App\Models\VendorContact; +use App\Utils\Ninja; +use App\Utils\Traits\MakesHash; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Storage; class CompanyExport implements ShouldQueue { @@ -461,13 +460,15 @@ class CompanyExport implements ShouldQueue Storage::disk(config('filesystems.default'))->put('backups/'.$file_name, file_get_contents($zip_path)); - if(file_exists($zip_path)) - unlink($zip_path); + if(file_exists($zip_path)) { + unlink($zip_path); + } - if(Ninja::isSelfHost()) + if(Ninja::isSelfHost()) { $storage_path = 'backups/'.$file_name; - else + } else { $storage_path = Storage::disk(config('filesystems.default'))->path('backups/'.$file_name); + } $url = Cache::get($this->hash); @@ -492,8 +493,9 @@ class CompanyExport implements ShouldQueue if (Ninja::isHosted()) { sleep(3); - if(file_exists($zip_path)) + if(file_exists($zip_path)) { unlink($zip_path); + } } } } diff --git a/app/Jobs/Company/CompanyTaxRate.php b/app/Jobs/Company/CompanyTaxRate.php index 886704fa35..9bb1eb470b 100644 --- a/app/Jobs/Company/CompanyTaxRate.php +++ b/app/Jobs/Company/CompanyTaxRate.php @@ -11,17 +11,17 @@ namespace App\Jobs\Company; -use App\Models\Company; -use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; -use App\DataProviders\USStates; -use Illuminate\Queue\SerializesModels; use App\DataMapper\Tax\ZipTax\Response; -use Illuminate\Queue\InteractsWithQueue; +use App\DataProviders\USStates; +use App\Libraries\MultiDB; +use App\Models\Company; use App\Services\Tax\Providers\TaxProvider; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; +use Illuminate\Queue\SerializesModels; class CompanyTaxRate implements ShouldQueue { @@ -53,21 +53,21 @@ class CompanyTaxRate implements ShouldQueue /** State must be calculated else default to the company state for taxes */ if(array_key_exists($this->company->settings->state, USStates::get())) { $calculated_state = $this->company->settings->state; - } - else { + } else { - try{ + try { $calculated_state = USStates::getState($this->company->settings->postal_code); - } - catch(\Exception $e){ + } catch(\Exception $e) { nlog("could not calculate state from postal code => {$this->company->settings->postal_code} or from state {$this->company->settings->state}"); } - if(!$calculated_state && $this->company->tax_data?->seller_subregion) + if(!$calculated_state && $this->company->tax_data?->seller_subregion) { $calculated_state = $this->company->tax_data?->seller_subregion; + } - if(!$calculated_state) + if(!$calculated_state) { return; + } } @@ -93,7 +93,8 @@ class CompanyTaxRate implements ShouldQueue return [new WithoutOverlapping($this->company->id)]; } - public function failed($e){ + public function failed($e) + { nlog($e->getMessage()); } -} \ No newline at end of file +} diff --git a/app/Jobs/Company/CreateCompany.php b/app/Jobs/Company/CreateCompany.php index 90bddda492..a9377fa478 100644 --- a/app/Jobs/Company/CreateCompany.php +++ b/app/Jobs/Company/CreateCompany.php @@ -11,16 +11,16 @@ namespace App\Jobs\Company; -use App\Utils\Ninja; +use App\DataMapper\ClientRegistrationFields; +use App\DataMapper\CompanySettings; +use App\DataMapper\Tax\TaxModel; +use App\Factory\TaxRateFactory; +use App\Libraries\MultiDB; use App\Models\Company; use App\Models\Country; -use App\Libraries\MultiDB; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; -use App\DataMapper\Tax\TaxModel; -use App\DataMapper\CompanySettings; use Illuminate\Foundation\Bus\Dispatchable; -use App\DataMapper\ClientRegistrationFields; -use App\Factory\TaxRateFactory; class CreateCompany { @@ -55,7 +55,7 @@ class CreateCompany $settings->name = isset($this->request['name']) ? $this->request['name'] : ''; - if($country_id = $this->resolveCountry()){ + if($country_id = $this->resolveCountry()) { $settings->country_id = $country_id; } @@ -95,33 +95,34 @@ class CreateCompany * * @return string */ - private function resolveCountry(): string + private function resolveCountry(): string { - try{ + try { $ip = request()->ip(); - if(request()->hasHeader('cf-ipcountry')){ + if(request()->hasHeader('cf-ipcountry')) { $c = Country::where('iso_3166_2', request()->header('cf-ipcountry'))->first(); - if($c) + if($c) { return (string)$c->id; + } } $details = json_decode(file_get_contents("http://ip-api.com/json/{$ip}")); - if($details && property_exists($details, 'countryCode')){ + if($details && property_exists($details, 'countryCode')) { $c = Country::where('iso_3166_2', $details->countryCode)->first(); - if($c) + if($c) { return (string)$c->id; + } } - } - catch(\Exception $e){ + } catch(\Exception $e) { nlog("Could not resolve country => {$e->getMessage()}"); } @@ -163,8 +164,7 @@ class CreateCompany return $company; - } - catch(\Exception $e){ + } catch(\Exception $e) { nlog("SETUP: could not complete setup for Spanish Locale"); } @@ -206,8 +206,7 @@ class CreateCompany return $company; - } - catch(\Exception $e){ + } catch(\Exception $e) { nlog($e->getMessage()); nlog("SETUP: could not complete setup for Australian Locale"); } diff --git a/app/Jobs/Credit/ZipCredits.php b/app/Jobs/Credit/ZipCredits.php index 2239fad4f8..88a2d66d51 100644 --- a/app/Jobs/Credit/ZipCredits.php +++ b/app/Jobs/Credit/ZipCredits.php @@ -11,7 +11,6 @@ namespace App\Jobs\Credit; -use App\Jobs\Entity\CreateEntityPdf; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Util\UnlinkFile; @@ -31,8 +30,6 @@ class ZipCredits implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public $settings; - public $tries = 1; public function __construct(protected array $credit_ids, protected Company $company, protected User $user) @@ -48,7 +45,7 @@ class ZipCredits implements ShouldQueue { MultiDB::setDb($this->company->db); - $this->settings = $this->company->settings; + $settings = $this->company->settings; $zipFile = new \PhpZip\ZipFile(); $file_name = now()->addSeconds($this->company->timezone_offset())->format('Y-m-d-h-m-s').'_'.str_replace(' ', '_', trans('texts.credits')).'.zip'; @@ -58,7 +55,7 @@ class ZipCredits implements ShouldQueue try { foreach ($invitations as $invitation) { - $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $this->company->db))->handle(); + $file = (new \App\Jobs\Entity\CreateRawPdf($invitation))->handle(); $zipFile->addFromString($invitation->credit->numberFormatter() . '.pdf', $file); } @@ -67,7 +64,7 @@ class ZipCredits implements ShouldQueue $nmo = new NinjaMailerObject; $nmo->mailable = new DownloadCredits(Storage::url($path.$file_name), $this->company); $nmo->to_user = $this->user; - $nmo->settings = $this->settings; + $nmo->settings = $settings; $nmo->company = $this->company; NinjaMailerJob::dispatch($nmo); diff --git a/app/Jobs/Cron/AutoBill.php b/app/Jobs/Cron/AutoBill.php index 5376571d7c..cc48b91423 100644 --- a/app/Jobs/Cron/AutoBill.php +++ b/app/Jobs/Cron/AutoBill.php @@ -11,14 +11,14 @@ namespace App\Jobs\Cron; -use App\Models\Invoice; -use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; use App\Jobs\Entity\EmailEntity; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; +use App\Libraries\MultiDB; +use App\Models\Invoice; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; class AutoBill implements ShouldQueue { @@ -60,8 +60,7 @@ class AutoBill implements ShouldQueue } catch (\Exception $e) { nlog("Failed to capture payment for {$this->invoice_id} ->".$e->getMessage()); - if($this->send_email_on_failure && $invoice) - { + if($this->send_email_on_failure && $invoice) { $invoice->invitations->each(function ($invitation) use ($invoice) { if ($invitation->contact && ! $invitation->contact->trashed() && strlen($invitation->contact->email) >= 1 && $invoice->client->getSetting('auto_email_invoice')) { diff --git a/app/Jobs/Cron/AutoBillCron.php b/app/Jobs/Cron/AutoBillCron.php index cf2c5f987f..ff3c2c2955 100644 --- a/app/Jobs/Cron/AutoBillCron.php +++ b/app/Jobs/Cron/AutoBillCron.php @@ -11,11 +11,11 @@ namespace App\Jobs\Cron; -use App\Models\Invoice; use App\Libraries\MultiDB; +use App\Models\Invoice; +use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Auth; -use Illuminate\Foundation\Bus\Dispatchable; class AutoBillCron { diff --git a/app/Jobs/Cron/RecurringExpensesCron.php b/app/Jobs/Cron/RecurringExpensesCron.php index 55eee07e5b..3b38aafb0c 100644 --- a/app/Jobs/Cron/RecurringExpensesCron.php +++ b/app/Jobs/Cron/RecurringExpensesCron.php @@ -11,16 +11,16 @@ namespace App\Jobs\Cron; -use App\Utils\Ninja; +use App\Events\Expense\ExpenseWasCreated; +use App\Factory\RecurringExpenseToExpenseFactory; use App\Libraries\MultiDB; -use Illuminate\Support\Carbon; use App\Models\RecurringExpense; use App\Models\RecurringInvoice; -use Illuminate\Support\Facades\Auth; +use App\Utils\Ninja; use App\Utils\Traits\GeneratesCounter; -use App\Events\Expense\ExpenseWasCreated; use Illuminate\Foundation\Bus\Dispatchable; -use App\Factory\RecurringExpenseToExpenseFactory; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Auth; class RecurringExpensesCron { @@ -105,8 +105,9 @@ class RecurringExpensesCron $expense = RecurringExpenseToExpenseFactory::create($recurring_expense); $expense->saveQuietly(); - if($expense->company->mark_expenses_paid) + if($expense->company->mark_expenses_paid) { $expense->payment_date = now()->format('Y-m-d'); + } $expense->number = $this->getNextExpenseNumber($expense); $expense->saveQuietly(); diff --git a/app/Jobs/Cron/RecurringInvoicesCron.php b/app/Jobs/Cron/RecurringInvoicesCron.php index edd57acf26..895a172a79 100644 --- a/app/Jobs/Cron/RecurringInvoicesCron.php +++ b/app/Jobs/Cron/RecurringInvoicesCron.php @@ -11,13 +11,13 @@ namespace App\Jobs\Cron; -use App\Models\Invoice; -use App\Libraries\MultiDB; -use Illuminate\Support\Carbon; -use App\Models\RecurringInvoice; -use Illuminate\Support\Facades\Auth; -use Illuminate\Foundation\Bus\Dispatchable; use App\Jobs\RecurringInvoice\SendRecurring; +use App\Libraries\MultiDB; +use App\Models\Invoice; +use App\Models\RecurringInvoice; +use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Auth; class RecurringInvoicesCron { diff --git a/app/Jobs/Cron/SubscriptionCron.php b/app/Jobs/Cron/SubscriptionCron.php index c77a627695..efa1da9c24 100644 --- a/app/Jobs/Cron/SubscriptionCron.php +++ b/app/Jobs/Cron/SubscriptionCron.php @@ -11,11 +11,11 @@ namespace App\Jobs\Cron; -use App\Models\Invoice; use App\Libraries\MultiDB; -use Illuminate\Support\Facades\Auth; +use App\Models\Invoice; use App\Utils\Traits\SubscriptionHooker; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Support\Facades\Auth; class SubscriptionCron { diff --git a/app/Jobs/Cron/UpdateCalculatedFields.php b/app/Jobs/Cron/UpdateCalculatedFields.php index 865d3ed123..77a629fce3 100644 --- a/app/Jobs/Cron/UpdateCalculatedFields.php +++ b/app/Jobs/Cron/UpdateCalculatedFields.php @@ -11,11 +11,10 @@ namespace App\Jobs\Cron; -use App\Models\Payment; -use App\Models\Project; use App\Libraries\MultiDB; -use Illuminate\Support\Facades\Auth; +use App\Models\Project; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Support\Facades\Auth; class UpdateCalculatedFields { @@ -43,15 +42,15 @@ class UpdateCalculatedFields if (! config('ninja.db.multi_db_enabled')) { - Project::query()->with('tasks')->whereHas('tasks', function ($query){ - $query->where('updated_at', '>', now()->subHours(2)); + Project::query()->with('tasks')->whereHas('tasks', function ($query) { + $query->where('updated_at', '>', now()->subHours(2)); }) ->cursor() ->each(function ($project) { $project->current_hours = $this->calculateDuration($project); $project->save(); - }); + }); @@ -61,14 +60,14 @@ class UpdateCalculatedFields MultiDB::setDB($db); - Project::query()->with('tasks')->whereHas('tasks', function ($query){ + Project::query()->with('tasks')->whereHas('tasks', function ($query) { $query->where('updated_at', '>', now()->subHours(2)); - }) - ->cursor() - ->each(function ($project) { - $project->current_hours = $this->calculateDuration($project); - $project->save(); - }); + }) + ->cursor() + ->each(function ($project) { + $project->current_hours = $this->calculateDuration($project); + $project->save(); + }); } } @@ -80,16 +79,17 @@ class UpdateCalculatedFields $project->tasks->each(function ($task) use (&$duration) { - if(is_iterable($task->time_log)) { + if(is_iterable(json_decode($task->time_log) )) { + foreach(json_decode($task->time_log) as $log) { - $start_time = $log[0]; - $end_time = $log[1] == 0 ? time() : $log[1]; + $start_time = $log[0]; + $end_time = $log[1] == 0 ? time() : $log[1]; - $duration += $end_time - $start_time; + $duration += $end_time - $start_time; + } } - } }); @@ -97,7 +97,3 @@ class UpdateCalculatedFields } } - - - - diff --git a/app/Jobs/Entity/CreateEntityPdf.php b/app/Jobs/Entity/CreateEntityPdf.php deleted file mode 100644 index 7ef89d2c3e..0000000000 --- a/app/Jobs/Entity/CreateEntityPdf.php +++ /dev/null @@ -1,294 +0,0 @@ -invitation = $invitation; - - if ($invitation instanceof InvoiceInvitation) { - $this->entity = $invitation->invoice; - $this->entity_string = 'invoice'; - } elseif ($invitation instanceof QuoteInvitation) { - $this->entity = $invitation->quote; - $this->entity_string = 'quote'; - } elseif ($invitation instanceof CreditInvitation) { - $this->entity = $invitation->credit; - $this->entity_string = 'credit'; - } elseif ($invitation instanceof RecurringInvoiceInvitation) { - $this->entity = $invitation->recurring_invoice; - $this->entity_string = 'recurring_invoice'; - } - - $this->company = $invitation->company; - - $this->contact = $invitation->contact; - - $this->client = $invitation->contact->client; - $this->client->load('company'); - - $this->disk = $disk ?? config('filesystems.default'); - } - - public function handle() - { - MultiDB::setDb($this->company->db); - - /* Forget the singleton*/ - App::forgetInstance('translator'); - - /* Init a new copy of the translator*/ - $t = app('translator'); - /* Set the locale*/ - App::setLocale($this->client->locale()); - - /* Set customized translations _NOW_ */ - $t->replace(Ninja::transformTranslations($this->client->getMergedSettings())); - - if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { - return (new Phantom)->generate($this->invitation); - } - - $entity_design_id = ''; - $path = ''; - - if ($this->entity instanceof Invoice) { - $path = $this->client->invoice_filepath($this->invitation); - $entity_design_id = 'invoice_design_id'; - } elseif ($this->entity instanceof Quote) { - $path = $this->client->quote_filepath($this->invitation); - $entity_design_id = 'quote_design_id'; - } elseif ($this->entity instanceof Credit) { - $path = $this->client->credit_filepath($this->invitation); - $entity_design_id = 'credit_design_id'; - } elseif ($this->entity instanceof RecurringInvoice) { - $path = $this->client->recurring_invoice_filepath($this->invitation); - $entity_design_id = 'invoice_design_id'; - } - - $file_path = $path.$this->entity->numberFormatter().'.pdf'; - - $entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->client->getSetting($entity_design_id)); - - /** @var \App\Models\Design $design */ - $design = Design::withTrashed()->find($entity_design_id); - - /* Catch all in case migration doesn't pass back a valid design */ - if (! $design) { - $design = Design::find(2); - } - - $html = new HtmlEngine($this->invitation); - - if ($design->is_custom) { - $options = [ - 'custom_partials' => json_decode(json_encode($design->design), true), - ]; - $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); - } else { - $template = new PdfMakerDesign(strtolower($design->name)); - } - - $variables = $html->generateLabelsAndValues(); - - $state = [ - 'template' => $template->elements([ - 'client' => $this->client, - 'entity' => $this->entity, - 'pdf_variables' => (array) $this->company->settings->pdf_variables, - '$product' => $design->design->product, - 'variables' => $variables, - ]), - 'variables' => $variables, - 'options' => [ - 'all_pages_header' => $this->entity->client->getSetting('all_pages_header'), - 'all_pages_footer' => $this->entity->client->getSetting('all_pages_footer'), - ], - 'process_markdown' => $this->entity->client->company->markdown_enabled, - ]; - - $maker = new PdfMakerService($state); - - $maker - ->design($template) - ->build(); - - $pdf = null; - - try { - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { - $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); - - $numbered_pdf = $this->pageNumbering($pdf, $this->company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - } else { - $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true)); - - $numbered_pdf = $this->pageNumbering($pdf, $this->company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - } - } catch (\Exception $e) { - nlog(print_r($e->getMessage(), 1)); - } - - if (config('ninja.log_pdf_html')) { - info($maker->getCompiledHTML()); - } - - if($this->entity_string == "invoice" && $this->client->getSetting('enable_e_invoice')) - { - $pdf = $this->checkEInvoice($pdf); - } - - if ($pdf) { - try { - Storage::disk($this->disk)->put($file_path, $pdf); - } catch (\Exception $e) { - throw new FilePermissionsFailure($e->getMessage()); - } - } - - $this->invitation = null; - // $this->entity = null; - $this->company = null; - $this->client = null; - $this->contact = null; - $maker = null; - $state = null; - - return $file_path; - } - - /** - * Switch to determine if we need to embed the xml into the PDF itself - * - * @param string $pdf - * @return string - */ - private function checkEInvoice(string $pdf): string - { - if(!$this->entity instanceof Invoice) - return $pdf; - - $e_invoice_type = $this->entity->client->getSetting('e_invoice_type'); - - switch ($e_invoice_type) { - case "EN16931": - case "XInvoice_2_2": - case "XInvoice_2_1": - case "XInvoice_2_0": - case "XInvoice_1_0": - case "XInvoice-Extended": - case "XInvoice-BasicWL": - case "XInvoice-Basic": - return $this->embedEInvoiceZuGFerD($pdf) ?? $pdf; - //case "Facturae_3.2": - //case "Facturae_3.2.1": - //case "Facturae_3.2.2": - // - default: - return $pdf; - } - - } - - /** - * Embed the .xml file into the PDF - * - * @param string $pdf - * @return string - */ - private function embedEInvoiceZuGFerD(string $pdf): string - { - try { - - $e_rechnung = (new CreateEInvoice($this->entity, true))->handle(); - $pdfBuilder = new ZugferdDocumentPdfBuilder($e_rechnung, $pdf); - $pdfBuilder->generateDocument(); - return $pdfBuilder->downloadString(basename($this->entity->getFileName())); - - } catch (\Exception $e) { - nlog("E_Invoice Merge failed - " . $e->getMessage()); - } - - return $pdf; - } - - - public function failed($e) - { - } -} diff --git a/app/Jobs/Entity/CreateRawPdf.php b/app/Jobs/Entity/CreateRawPdf.php index 593566577b..70c5754f92 100644 --- a/app/Jobs/Entity/CreateRawPdf.php +++ b/app/Jobs/Entity/CreateRawPdf.php @@ -17,12 +17,12 @@ use App\Models\Credit; use App\Models\Design; use App\Models\Invoice; use App\Utils\HtmlEngine; -use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; +use App\Models\PurchaseOrder; use App\Models\QuoteInvitation; use App\Utils\Traits\MakesHash; use App\Models\CreditInvitation; use App\Models\RecurringInvoice; +use App\Services\Pdf\PdfService; use App\Utils\PhantomJS\Phantom; use App\Models\InvoiceInvitation; use App\Utils\HostedPDF\NinjaPdf; @@ -31,23 +31,20 @@ use Illuminate\Support\Facades\App; use App\Jobs\Invoice\CreateEInvoice; use App\Utils\Traits\NumberFormatter; use App\Utils\Traits\MakesInvoiceHtml; -use Illuminate\Queue\SerializesModels; +use App\Models\PurchaseOrderInvitation; use App\Utils\Traits\Pdf\PageNumbering; -use Illuminate\Queue\InteractsWithQueue; use App\Exceptions\FilePermissionsFailure; use App\Models\RecurringInvoiceInvitation; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; use horstoeko\zugferd\ZugferdDocumentPdfBuilder; use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\PdfMaker as PdfMakerService; -class CreateRawPdf implements ShouldQueue +class CreateRawPdf { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering; + use NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering; - public Invoice | Credit | Quote | RecurringInvoice $entity; + public Invoice | Credit | Quote | RecurringInvoice | PurchaseOrder $entity; public $company; @@ -58,13 +55,10 @@ class CreateRawPdf implements ShouldQueue public $entity_string = ''; /** - * Create a new job instance. - * * @param $invitation */ - public function __construct($invitation, $db) + public function __construct($invitation, private ?string $type = null) { - MultiDB::setDb($db); $this->invitation = $invitation; @@ -80,15 +74,47 @@ class CreateRawPdf implements ShouldQueue } elseif ($invitation instanceof RecurringInvoiceInvitation) { $this->entity = $invitation->recurring_invoice; $this->entity_string = 'recurring_invoice'; + } elseif ($invitation instanceof PurchaseOrderInvitation){ + $this->entity = $invitation->purchase_order; + $this->entity_string = 'purchase_order'; } $this->company = $invitation->company; - $this->contact = $invitation->contact; } + private function resolveType(): string + { + if($this->type) + return $this->type; + + $type = 'product'; + + match($this->entity_string) { + 'purchase_order' => $type = 'purchase_order', + 'invoice' => $type = 'product', + 'quote' => $type = 'product', + 'credit' => $type = 'product', + 'recurring_invoice' => $type = 'product', + }; + + return $type; + + } + public function handle() { + /** Testing this override to improve PDF generation performance */ + $ps = new PdfService($this->invitation, $this->resolveType(), [ + 'client' => $this->entity->client ?? false, + 'vendor' => $this->entity->vendor ?? false, + "{$this->entity_string}s" => [$this->entity], + ]); + + $pdf = $ps->boot()->getPdf(); + return $pdf; + nlog("pdf timer = ". $ps->execution_time); + /* Forget the singleton*/ App::forgetInstance('translator'); @@ -157,6 +183,9 @@ class CreateRawPdf implements ShouldQueue 'options' => [ 'all_pages_header' => $this->entity->client->getSetting('all_pages_header'), 'all_pages_footer' => $this->entity->client->getSetting('all_pages_footer'), + 'client' => $this->entity->client, + 'entity' => $this->entity, + 'variables' => $variables, ], 'process_markdown' => $this->entity->client->company->markdown_enabled, ]; @@ -220,8 +249,9 @@ class CreateRawPdf implements ShouldQueue */ private function checkEInvoice(string $pdf): string { - if(!$this->entity instanceof Invoice || !$this->company->getSetting('enable_e_invoice')) + if(!$this->entity instanceof Invoice || !$this->company->getSetting('enable_e_invoice')) { return $pdf; + } $e_invoice_type = $this->entity->client->getSetting('e_invoice_type'); diff --git a/app/Jobs/Entity/EmailEntity.php b/app/Jobs/Entity/EmailEntity.php index 41473f1b8f..f25d101e16 100644 --- a/app/Jobs/Entity/EmailEntity.php +++ b/app/Jobs/Entity/EmailEntity.php @@ -11,7 +11,6 @@ namespace App\Jobs\Entity; -use App\Events\Invoice\InvoiceWasEmailedAndFailed; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Libraries\MultiDB; diff --git a/app/Jobs/Invoice/CheckGatewayFee.php b/app/Jobs/Invoice/CheckGatewayFee.php index e7a9784270..3f79e41bcf 100644 --- a/app/Jobs/Invoice/CheckGatewayFee.php +++ b/app/Jobs/Invoice/CheckGatewayFee.php @@ -11,14 +11,14 @@ namespace App\Jobs\Invoice; -use App\Models\Invoice; use App\Libraries\MultiDB; +use App\Models\Invoice; use Illuminate\Bus\Queueable; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; +use Illuminate\Queue\SerializesModels; class CheckGatewayFee implements ShouldQueue { diff --git a/app/Jobs/Invoice/CreateEInvoice.php b/app/Jobs/Invoice/CreateEInvoice.php index c68662c4b1..b3f64776ea 100644 --- a/app/Jobs/Invoice/CreateEInvoice.php +++ b/app/Jobs/Invoice/CreateEInvoice.php @@ -12,17 +12,17 @@ namespace App\Jobs\Invoice; -use App\Utils\Ninja; use App\Models\Invoice; -use horstoeko\zugferd\ZugferdDocumentBuilder; -use Illuminate\Bus\Queueable; -use Illuminate\Support\Facades\App; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; use App\Services\Invoice\EInvoice\FacturaEInvoice; use App\Services\Invoice\EInvoice\ZugferdEInvoice; +use App\Utils\Ninja; +use horstoeko\zugferd\ZugferdDocumentBuilder; +use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\App; class CreateEInvoice implements ShouldQueue { diff --git a/app/Jobs/Invoice/InjectSignature.php b/app/Jobs/Invoice/InjectSignature.php index b296b43e6f..7f161b6531 100644 --- a/app/Jobs/Invoice/InjectSignature.php +++ b/app/Jobs/Invoice/InjectSignature.php @@ -4,10 +4,10 @@ namespace App\Jobs\Invoice; use App\Models\PurchaseOrder; use Illuminate\Bus\Queueable; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; class InjectSignature implements ShouldQueue { @@ -34,19 +34,20 @@ class InjectSignature implements ShouldQueue { $invitation = false; - if($this->entity instanceof PurchaseOrder){ + if($this->entity instanceof PurchaseOrder) { $invitation = $this->entity->invitations()->where('vendor_contact_id', $this->contact_id)->first(); - if(!$invitation) + if(!$invitation) { $invitation = $this->entity->invitations->first(); + } - } - else { + } else { $invitation = $this->entity->invitations()->where('client_contact_id', $this->contact_id)->first(); - if(!$invitation) + if(!$invitation) { $invitation = $this->entity->invitations->first(); + } } if (! $invitation) { diff --git a/app/Jobs/Invoice/InvoiceWorkflowSettings.php b/app/Jobs/Invoice/InvoiceWorkflowSettings.php index 615b43ad92..9994971089 100644 --- a/app/Jobs/Invoice/InvoiceWorkflowSettings.php +++ b/app/Jobs/Invoice/InvoiceWorkflowSettings.php @@ -12,7 +12,6 @@ namespace App\Jobs\Invoice; -use App\Models\Client; use App\Models\Invoice; use App\Repositories\BaseRepository; use Illuminate\Bus\Queueable; diff --git a/app/Jobs/Invoice/ZipInvoices.php b/app/Jobs/Invoice/ZipInvoices.php index f7292988b0..82ddade105 100644 --- a/app/Jobs/Invoice/ZipInvoices.php +++ b/app/Jobs/Invoice/ZipInvoices.php @@ -11,7 +11,6 @@ namespace App\Jobs\Invoice; -use App\Jobs\Entity\CreateEntityPdf; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Util\UnlinkFile; @@ -30,14 +29,6 @@ class ZipInvoices implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public $invoices; - - private $company; - - private $user; - - public $settings; - public $tries = 1; /** @@ -47,15 +38,8 @@ class ZipInvoices implements ShouldQueue * @deprecated confirm to be deleted * Create a new job instance. */ - public function __construct($invoices, Company $company, User $user) + public function __construct(public mixed $invoices, public Company $company, public User $user) { - $this->invoices = $invoices; - - $this->company = $company; - - $this->user = $user; - - $this->settings = $company->settings; } /** @@ -66,6 +50,7 @@ class ZipInvoices implements ShouldQueue public function handle(): void { MultiDB::setDb($this->company->db); + $settings = $this->company->settings; // create new zip object $zipFile = new \PhpZip\ZipFile(); @@ -93,7 +78,7 @@ class ZipInvoices implements ShouldQueue $nmo = new NinjaMailerObject; $nmo->mailable = new DownloadInvoices(Storage::url($path.$file_name), $this->company); $nmo->to_user = $this->user; - $nmo->settings = $this->settings; + $nmo->settings = $settings; $nmo->company = $this->company; NinjaMailerJob::dispatch($nmo); diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php index eed243b27d..9fc9acf136 100644 --- a/app/Jobs/Mail/NinjaMailerJob.php +++ b/app/Jobs/Mail/NinjaMailerJob.php @@ -492,7 +492,7 @@ class NinjaMailerJob implements ShouldQueue */ private function preFlightChecksFail(): bool { - /* Always send regardless */ + /* Always send regardless */ if($this->override) { return false; } diff --git a/app/Jobs/Ninja/CheckACHStatus.php b/app/Jobs/Ninja/CheckACHStatus.php index 371681cf73..32cf8bd789 100644 --- a/app/Jobs/Ninja/CheckACHStatus.php +++ b/app/Jobs/Ninja/CheckACHStatus.php @@ -11,14 +11,14 @@ namespace App\Jobs\Ninja; -use App\Models\Payment; use App\Libraries\MultiDB; -use Illuminate\Bus\Queueable; use App\Models\ClientGatewayToken; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; +use App\Models\Payment; +use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; class CheckACHStatus implements ShouldQueue { @@ -77,7 +77,7 @@ class CheckACHStatus implements ShouldQueue }); Payment::where('status_id', 1) - ->whereHas('company_gateway', function ($q){ + ->whereHas('company_gateway', function ($q) { $q->whereIn('gateway_key', ['d14dd26a47cecc30fdd65700bfb67b34', 'd14dd26a37cecc30fdd65700bfb55b23']); }) ->cursor() @@ -124,4 +124,4 @@ class CheckACHStatus implements ShouldQueue } } -} \ No newline at end of file +} diff --git a/app/Jobs/Ninja/CheckCompanyData.php b/app/Jobs/Ninja/CheckCompanyData.php index 9899bdff77..c26827ad99 100644 --- a/app/Jobs/Ninja/CheckCompanyData.php +++ b/app/Jobs/Ninja/CheckCompanyData.php @@ -11,7 +11,6 @@ namespace App\Jobs\Ninja; -use App\Models\ClientContact; use App\Models\Company; use App\Models\CompanyLedger; use App\Models\Credit; diff --git a/app/Jobs/Ninja/TaskScheduler.php b/app/Jobs/Ninja/TaskScheduler.php index 307ffb07bf..dfb7616993 100644 --- a/app/Jobs/Ninja/TaskScheduler.php +++ b/app/Jobs/Ninja/TaskScheduler.php @@ -11,14 +11,14 @@ namespace App\Jobs\Ninja; -use App\Models\Scheduler; use App\Libraries\MultiDB; +use App\Models\Scheduler; use Illuminate\Bus\Queueable; -use Illuminate\Support\Facades\Auth; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Auth; //@rebuild it class TaskScheduler implements ShouldQueue diff --git a/app/Jobs/Payment/EmailPayment.php b/app/Jobs/Payment/EmailPayment.php index dd6a7f129a..f8729f707e 100644 --- a/app/Jobs/Payment/EmailPayment.php +++ b/app/Jobs/Payment/EmailPayment.php @@ -31,14 +31,8 @@ class EmailPayment implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public $payment; - public $email_builder; - private $contact; - - private $company; - public $settings; /** @@ -49,11 +43,8 @@ class EmailPayment implements ShouldQueue * @param $contact * @param $company */ - public function __construct(Payment $payment, Company $company, ?ClientContact $contact) + public function __construct(public Payment $payment, private Company $company, private ?ClientContact $contact) { - $this->payment = $payment; - $this->contact = $contact; - $this->company = $company; $this->settings = $payment->client->getMergedSettings(); } @@ -87,14 +78,15 @@ class EmailPayment implements ShouldQueue if ($this->payment->invoices && $this->payment->invoices->count() >= 1) { - if($this->contact){ + if($this->contact) { $invitation = $this->payment->invoices->first()->invitations()->where('client_contact_id', $this->contact->id)->first(); - } - else + } else { $invitation = $this->payment->invoices->first()->invitations()->first(); + } - if($invitation) + if($invitation) { $nmo->invitation = $invitation; + } } diff --git a/app/Jobs/Payment/EmailRefundPayment.php b/app/Jobs/Payment/EmailRefundPayment.php index bbc062f791..1ec374ab1b 100644 --- a/app/Jobs/Payment/EmailRefundPayment.php +++ b/app/Jobs/Payment/EmailRefundPayment.php @@ -32,14 +32,8 @@ class EmailRefundPayment implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public $payment; - public $email_builder; - private $contact; - - private $company; - public $settings; /** @@ -50,11 +44,8 @@ class EmailRefundPayment implements ShouldQueue * @param $contact * @param $company */ - public function __construct(Payment $payment, Company $company, ClientContact $contact) + public function __construct(public Payment $payment, private Company $company, private ?ClientContact $contact) { - $this->payment = $payment; - $this->contact = $contact; - $this->company = $company; $this->settings = $payment->client->getMergedSettings(); } @@ -84,7 +75,9 @@ class EmailRefundPayment implements ShouldQueue $template_data['body'] = ctrans('texts.refunded_payment').' $payment.refundedDefault company invoice terms<\/p>","public_notes":"","private_notes":"","uses_inclusive_taxes":false,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"total_taxes":0,"is_amount_discount":true,"footer":"
Default invoice footer<\/p>","partial":0,"partial_due_date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","has_tasks":false,"has_expenses":false,"custom_surcharge1":0,"custom_surcharge2":0,"custom_surcharge3":0,"custom_surcharge4":0,"exchange_rate":1,"custom_surcharge_tax1":false,"custom_surcharge_tax2":false,"custom_surcharge_tax3":false,"custom_surcharge_tax4":false,"line_items":[{"_id":"1d9727b4-bc32-4c62-a291-3b595e638a3b","quantity":0,"cost":33,"product_key":"t1","product_cost":0,"notes":"task 1 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":0,"gross_line_total":0,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"Volej0WbjN","tax_amount":0,"expense_id":""},{"_id":"37e6f099-d7c9-47ad-aaf3-2de38942959c","quantity":5,"cost":123,"product_key":"t2","product_cost":0,"notes":"task 2 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":615,"gross_line_total":615,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"O5xe7pwa7r","tax_amount":0,"expense_id":""},{"_id":"d109e819-e839-4eeb-9c24-cd91cbfed7b5","quantity":5,"cost":33,"product_key":"t3","product_cost":0,"notes":"task 3 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":165,"gross_line_total":165,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"QK9b6B7bEv","tax_amount":0,"expense_id":""},{"_id":"ac64e02b-219c-4a18-9a7c-191dd5b8f21f","quantity":5,"cost":67,"product_key":"t4","product_cost":0,"notes":"task 4 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":335,"gross_line_total":335,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"qM7e5Rxa2v","tax_amount":0,"expense_id":""},{"_id":"7b6dcee1-7b07-49b7-bcfa-2129ef844f07","quantity":5,"cost":4,"product_key":"t5","product_cost":0,"notes":"task 5 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":20,"gross_line_total":20,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"KGRb4z2eBL","tax_amount":0,"expense_id":""},{"_id":"a8ef31c5-49ac-43f7-a40e-0e311b940589","quantity":5,"cost":11,"product_key":"t6","product_cost":0,"notes":"task 6 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":55,"gross_line_total":55,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"GELe3yrb69","tax_amount":0,"expense_id":""}],"entity_type":"invoice","reminder1_sent":"","reminder2_sent":"","reminder3_sent":"","reminder_last_sent":"","paid_to_date":444,"subscription_id":"","auto_bill_enabled":false,"tax_info":{},"invitations":{"data":[{"id":"WJxboZzagw","client_contact_id":"yMYerkEaOB","key":"i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","link":"http:\/\/ninja.test:8000\/client\/invoice\/i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"k8mepZ1bMy","client_contact_id":"gl9av2maG1","key":"H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","link":"http:\/\/ninja.test:8000\/client\/invoice\/H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"l4zbqQ3bpr","client_contact_id":"7LDdwpRe1Y","key":"viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","link":"http:\/\/ninja.test:8000\/client\/invoice\/viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""}]},"documents":{"data":[]}}}},{"id":"KGRb4z2eBL","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0039","description":"Omnis amet illum inventore.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695799099,"archived_at":0,"invoice_id":"mxkazm8eJ0","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":{"data":{"id":"mxkazm8eJ0","user_id":"wMvbmOeYAl","project_id":"","assigned_user_id":"","amount":1190,"balance":746,"client_id":"QJ0dN6dLOv","vendor_id":"","status_id":"3","design_id":"Wpmbk5ezJn","recurring_id":"","created_at":1695798363,"updated_at":1695799116,"archived_at":0,"is_deleted":false,"number":"0026","discount":0,"po_number":"","date":"2023-09-27","last_sent_date":"","next_send_date":"","due_date":"","terms":"
Default company invoice terms<\/p>","public_notes":"","private_notes":"","uses_inclusive_taxes":false,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"total_taxes":0,"is_amount_discount":true,"footer":"
Default invoice footer<\/p>","partial":0,"partial_due_date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","has_tasks":false,"has_expenses":false,"custom_surcharge1":0,"custom_surcharge2":0,"custom_surcharge3":0,"custom_surcharge4":0,"exchange_rate":1,"custom_surcharge_tax1":false,"custom_surcharge_tax2":false,"custom_surcharge_tax3":false,"custom_surcharge_tax4":false,"line_items":[{"_id":"1d9727b4-bc32-4c62-a291-3b595e638a3b","quantity":0,"cost":33,"product_key":"t1","product_cost":0,"notes":"task 1 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":0,"gross_line_total":0,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"Volej0WbjN","tax_amount":0,"expense_id":""},{"_id":"37e6f099-d7c9-47ad-aaf3-2de38942959c","quantity":5,"cost":123,"product_key":"t2","product_cost":0,"notes":"task 2 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":615,"gross_line_total":615,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"O5xe7pwa7r","tax_amount":0,"expense_id":""},{"_id":"d109e819-e839-4eeb-9c24-cd91cbfed7b5","quantity":5,"cost":33,"product_key":"t3","product_cost":0,"notes":"task 3 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":165,"gross_line_total":165,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"QK9b6B7bEv","tax_amount":0,"expense_id":""},{"_id":"ac64e02b-219c-4a18-9a7c-191dd5b8f21f","quantity":5,"cost":67,"product_key":"t4","product_cost":0,"notes":"task 4 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":335,"gross_line_total":335,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"qM7e5Rxa2v","tax_amount":0,"expense_id":""},{"_id":"7b6dcee1-7b07-49b7-bcfa-2129ef844f07","quantity":5,"cost":4,"product_key":"t5","product_cost":0,"notes":"task 5 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":20,"gross_line_total":20,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"KGRb4z2eBL","tax_amount":0,"expense_id":""},{"_id":"a8ef31c5-49ac-43f7-a40e-0e311b940589","quantity":5,"cost":11,"product_key":"t6","product_cost":0,"notes":"task 6 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":55,"gross_line_total":55,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"GELe3yrb69","tax_amount":0,"expense_id":""}],"entity_type":"invoice","reminder1_sent":"","reminder2_sent":"","reminder3_sent":"","reminder_last_sent":"","paid_to_date":444,"subscription_id":"","auto_bill_enabled":false,"tax_info":{},"invitations":{"data":[{"id":"WJxboZzagw","client_contact_id":"yMYerkEaOB","key":"i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","link":"http:\/\/ninja.test:8000\/client\/invoice\/i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"k8mepZ1bMy","client_contact_id":"gl9av2maG1","key":"H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","link":"http:\/\/ninja.test:8000\/client\/invoice\/H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"l4zbqQ3bpr","client_contact_id":"7LDdwpRe1Y","key":"viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","link":"http:\/\/ninja.test:8000\/client\/invoice\/viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""}]},"documents":{"data":[]}}}},{"id":"qM7e5Rxa2v","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0040","description":"Tempore dolore aut necessitatibus ex illo.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695799099,"archived_at":0,"invoice_id":"mxkazm8eJ0","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":{"data":{"id":"mxkazm8eJ0","user_id":"wMvbmOeYAl","project_id":"","assigned_user_id":"","amount":1190,"balance":746,"client_id":"QJ0dN6dLOv","vendor_id":"","status_id":"3","design_id":"Wpmbk5ezJn","recurring_id":"","created_at":1695798363,"updated_at":1695799116,"archived_at":0,"is_deleted":false,"number":"0026","discount":0,"po_number":"","date":"2023-09-27","last_sent_date":"","next_send_date":"","due_date":"","terms":"
Default company invoice terms<\/p>","public_notes":"","private_notes":"","uses_inclusive_taxes":false,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"total_taxes":0,"is_amount_discount":true,"footer":"
Default invoice footer<\/p>","partial":0,"partial_due_date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","has_tasks":false,"has_expenses":false,"custom_surcharge1":0,"custom_surcharge2":0,"custom_surcharge3":0,"custom_surcharge4":0,"exchange_rate":1,"custom_surcharge_tax1":false,"custom_surcharge_tax2":false,"custom_surcharge_tax3":false,"custom_surcharge_tax4":false,"line_items":[{"_id":"1d9727b4-bc32-4c62-a291-3b595e638a3b","quantity":0,"cost":33,"product_key":"t1","product_cost":0,"notes":"task 1 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":0,"gross_line_total":0,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"Volej0WbjN","tax_amount":0,"expense_id":""},{"_id":"37e6f099-d7c9-47ad-aaf3-2de38942959c","quantity":5,"cost":123,"product_key":"t2","product_cost":0,"notes":"task 2 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":615,"gross_line_total":615,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"O5xe7pwa7r","tax_amount":0,"expense_id":""},{"_id":"d109e819-e839-4eeb-9c24-cd91cbfed7b5","quantity":5,"cost":33,"product_key":"t3","product_cost":0,"notes":"task 3 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":165,"gross_line_total":165,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"QK9b6B7bEv","tax_amount":0,"expense_id":""},{"_id":"ac64e02b-219c-4a18-9a7c-191dd5b8f21f","quantity":5,"cost":67,"product_key":"t4","product_cost":0,"notes":"task 4 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":335,"gross_line_total":335,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"qM7e5Rxa2v","tax_amount":0,"expense_id":""},{"_id":"7b6dcee1-7b07-49b7-bcfa-2129ef844f07","quantity":5,"cost":4,"product_key":"t5","product_cost":0,"notes":"task 5 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":20,"gross_line_total":20,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"KGRb4z2eBL","tax_amount":0,"expense_id":""},{"_id":"a8ef31c5-49ac-43f7-a40e-0e311b940589","quantity":5,"cost":11,"product_key":"t6","product_cost":0,"notes":"task 6 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":55,"gross_line_total":55,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"GELe3yrb69","tax_amount":0,"expense_id":""}],"entity_type":"invoice","reminder1_sent":"","reminder2_sent":"","reminder3_sent":"","reminder_last_sent":"","paid_to_date":444,"subscription_id":"","auto_bill_enabled":false,"tax_info":{},"invitations":{"data":[{"id":"WJxboZzagw","client_contact_id":"yMYerkEaOB","key":"i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","link":"http:\/\/ninja.test:8000\/client\/invoice\/i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"k8mepZ1bMy","client_contact_id":"gl9av2maG1","key":"H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","link":"http:\/\/ninja.test:8000\/client\/invoice\/H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"l4zbqQ3bpr","client_contact_id":"7LDdwpRe1Y","key":"viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","link":"http:\/\/ninja.test:8000\/client\/invoice\/viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""}]},"documents":{"data":[]}}}},{"id":"QK9b6B7bEv","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0041","description":"Ipsam eos deleniti delectus.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695799099,"archived_at":0,"invoice_id":"mxkazm8eJ0","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":{"data":{"id":"mxkazm8eJ0","user_id":"wMvbmOeYAl","project_id":"","assigned_user_id":"","amount":1190,"balance":746,"client_id":"QJ0dN6dLOv","vendor_id":"","status_id":"3","design_id":"Wpmbk5ezJn","recurring_id":"","created_at":1695798363,"updated_at":1695799116,"archived_at":0,"is_deleted":false,"number":"0026","discount":0,"po_number":"","date":"2023-09-27","last_sent_date":"","next_send_date":"","due_date":"","terms":"
Default company invoice terms<\/p>","public_notes":"","private_notes":"","uses_inclusive_taxes":false,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"total_taxes":0,"is_amount_discount":true,"footer":"
Default invoice footer<\/p>","partial":0,"partial_due_date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","has_tasks":false,"has_expenses":false,"custom_surcharge1":0,"custom_surcharge2":0,"custom_surcharge3":0,"custom_surcharge4":0,"exchange_rate":1,"custom_surcharge_tax1":false,"custom_surcharge_tax2":false,"custom_surcharge_tax3":false,"custom_surcharge_tax4":false,"line_items":[{"_id":"1d9727b4-bc32-4c62-a291-3b595e638a3b","quantity":0,"cost":33,"product_key":"t1","product_cost":0,"notes":"task 1 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":0,"gross_line_total":0,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"Volej0WbjN","tax_amount":0,"expense_id":""},{"_id":"37e6f099-d7c9-47ad-aaf3-2de38942959c","quantity":5,"cost":123,"product_key":"t2","product_cost":0,"notes":"task 2 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":615,"gross_line_total":615,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"O5xe7pwa7r","tax_amount":0,"expense_id":""},{"_id":"d109e819-e839-4eeb-9c24-cd91cbfed7b5","quantity":5,"cost":33,"product_key":"t3","product_cost":0,"notes":"task 3 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":165,"gross_line_total":165,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"QK9b6B7bEv","tax_amount":0,"expense_id":""},{"_id":"ac64e02b-219c-4a18-9a7c-191dd5b8f21f","quantity":5,"cost":67,"product_key":"t4","product_cost":0,"notes":"task 4 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":335,"gross_line_total":335,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"qM7e5Rxa2v","tax_amount":0,"expense_id":""},{"_id":"7b6dcee1-7b07-49b7-bcfa-2129ef844f07","quantity":5,"cost":4,"product_key":"t5","product_cost":0,"notes":"task 5 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":20,"gross_line_total":20,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"KGRb4z2eBL","tax_amount":0,"expense_id":""},{"_id":"a8ef31c5-49ac-43f7-a40e-0e311b940589","quantity":5,"cost":11,"product_key":"t6","product_cost":0,"notes":"task 6 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":55,"gross_line_total":55,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"GELe3yrb69","tax_amount":0,"expense_id":""}],"entity_type":"invoice","reminder1_sent":"","reminder2_sent":"","reminder3_sent":"","reminder_last_sent":"","paid_to_date":444,"subscription_id":"","auto_bill_enabled":false,"tax_info":{},"invitations":{"data":[{"id":"WJxboZzagw","client_contact_id":"yMYerkEaOB","key":"i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","link":"http:\/\/ninja.test:8000\/client\/invoice\/i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"k8mepZ1bMy","client_contact_id":"gl9av2maG1","key":"H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","link":"http:\/\/ninja.test:8000\/client\/invoice\/H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"l4zbqQ3bpr","client_contact_id":"7LDdwpRe1Y","key":"viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","link":"http:\/\/ninja.test:8000\/client\/invoice\/viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""}]},"documents":{"data":[]}}}},{"id":"O5xe7pwa7r","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0042","description":"Aperiam quae voluptas voluptatem vero.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695799099,"archived_at":0,"invoice_id":"mxkazm8eJ0","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":{"data":{"id":"mxkazm8eJ0","user_id":"wMvbmOeYAl","project_id":"","assigned_user_id":"","amount":1190,"balance":746,"client_id":"QJ0dN6dLOv","vendor_id":"","status_id":"3","design_id":"Wpmbk5ezJn","recurring_id":"","created_at":1695798363,"updated_at":1695799116,"archived_at":0,"is_deleted":false,"number":"0026","discount":0,"po_number":"","date":"2023-09-27","last_sent_date":"","next_send_date":"","due_date":"","terms":"
Default company invoice terms<\/p>","public_notes":"","private_notes":"","uses_inclusive_taxes":false,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"total_taxes":0,"is_amount_discount":true,"footer":"
Default invoice footer<\/p>","partial":0,"partial_due_date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","has_tasks":false,"has_expenses":false,"custom_surcharge1":0,"custom_surcharge2":0,"custom_surcharge3":0,"custom_surcharge4":0,"exchange_rate":1,"custom_surcharge_tax1":false,"custom_surcharge_tax2":false,"custom_surcharge_tax3":false,"custom_surcharge_tax4":false,"line_items":[{"_id":"1d9727b4-bc32-4c62-a291-3b595e638a3b","quantity":0,"cost":33,"product_key":"t1","product_cost":0,"notes":"task 1 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":0,"gross_line_total":0,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"Volej0WbjN","tax_amount":0,"expense_id":""},{"_id":"37e6f099-d7c9-47ad-aaf3-2de38942959c","quantity":5,"cost":123,"product_key":"t2","product_cost":0,"notes":"task 2 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":615,"gross_line_total":615,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"O5xe7pwa7r","tax_amount":0,"expense_id":""},{"_id":"d109e819-e839-4eeb-9c24-cd91cbfed7b5","quantity":5,"cost":33,"product_key":"t3","product_cost":0,"notes":"task 3 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":165,"gross_line_total":165,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"QK9b6B7bEv","tax_amount":0,"expense_id":""},{"_id":"ac64e02b-219c-4a18-9a7c-191dd5b8f21f","quantity":5,"cost":67,"product_key":"t4","product_cost":0,"notes":"task 4 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":335,"gross_line_total":335,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"qM7e5Rxa2v","tax_amount":0,"expense_id":""},{"_id":"7b6dcee1-7b07-49b7-bcfa-2129ef844f07","quantity":5,"cost":4,"product_key":"t5","product_cost":0,"notes":"task 5 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":20,"gross_line_total":20,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"KGRb4z2eBL","tax_amount":0,"expense_id":""},{"_id":"a8ef31c5-49ac-43f7-a40e-0e311b940589","quantity":5,"cost":11,"product_key":"t6","product_cost":0,"notes":"task 6 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":55,"gross_line_total":55,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"GELe3yrb69","tax_amount":0,"expense_id":""}],"entity_type":"invoice","reminder1_sent":"","reminder2_sent":"","reminder3_sent":"","reminder_last_sent":"","paid_to_date":444,"subscription_id":"","auto_bill_enabled":false,"tax_info":{},"invitations":{"data":[{"id":"WJxboZzagw","client_contact_id":"yMYerkEaOB","key":"i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","link":"http:\/\/ninja.test:8000\/client\/invoice\/i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"k8mepZ1bMy","client_contact_id":"gl9av2maG1","key":"H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","link":"http:\/\/ninja.test:8000\/client\/invoice\/H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"l4zbqQ3bpr","client_contact_id":"7LDdwpRe1Y","key":"viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","link":"http:\/\/ninja.test:8000\/client\/invoice\/viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""}]},"documents":{"data":[]}}}},{"id":"MVyb8MldvA","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0043","description":"Voluptatem iusto quod cupiditate.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695798883,"archived_at":0,"invoice_id":"","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":[]},{"id":"VWPe9DPdLy","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0044","description":"Ab occaecati ut in qui.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695798950,"archived_at":0,"invoice_id":"","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"X46dBXa79j","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":[]},{"id":"QnXe007exr","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0045","description":"At ratione dicta dicta ab earum.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695798883,"archived_at":0,"invoice_id":"","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":[]},{"id":"Wjnegn9dwZ","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0046","description":"Omnis dolores ducimus iusto maxime aut iure.","duration":0,"rate":0,"created_at":1695797987,"updated_at":1695798928,"archived_at":0,"invoice_id":"","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"4w9aAOdvMR","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":[]},{"id":"Volej0WbjN","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0047","description":"Possimus ut quia commodi voluptatem.","duration":0,"rate":33,"created_at":1695797987,"updated_at":1695799099,"archived_at":0,"invoice_id":"mxkazm8eJ0","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"mxkazYeJ0P","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":{"data":{"id":"mxkazm8eJ0","user_id":"wMvbmOeYAl","project_id":"","assigned_user_id":"","amount":1190,"balance":746,"client_id":"QJ0dN6dLOv","vendor_id":"","status_id":"3","design_id":"Wpmbk5ezJn","recurring_id":"","created_at":1695798363,"updated_at":1695799116,"archived_at":0,"is_deleted":false,"number":"0026","discount":0,"po_number":"","date":"2023-09-27","last_sent_date":"","next_send_date":"","due_date":"","terms":"
Default company invoice terms<\/p>","public_notes":"","private_notes":"","uses_inclusive_taxes":false,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"total_taxes":0,"is_amount_discount":true,"footer":"
Default invoice footer<\/p>","partial":0,"partial_due_date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","has_tasks":false,"has_expenses":false,"custom_surcharge1":0,"custom_surcharge2":0,"custom_surcharge3":0,"custom_surcharge4":0,"exchange_rate":1,"custom_surcharge_tax1":false,"custom_surcharge_tax2":false,"custom_surcharge_tax3":false,"custom_surcharge_tax4":false,"line_items":[{"_id":"1d9727b4-bc32-4c62-a291-3b595e638a3b","quantity":0,"cost":33,"product_key":"t1","product_cost":0,"notes":"task 1 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":0,"gross_line_total":0,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"Volej0WbjN","tax_amount":0,"expense_id":""},{"_id":"37e6f099-d7c9-47ad-aaf3-2de38942959c","quantity":5,"cost":123,"product_key":"t2","product_cost":0,"notes":"task 2 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":615,"gross_line_total":615,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"O5xe7pwa7r","tax_amount":0,"expense_id":""},{"_id":"d109e819-e839-4eeb-9c24-cd91cbfed7b5","quantity":5,"cost":33,"product_key":"t3","product_cost":0,"notes":"task 3 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":165,"gross_line_total":165,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"QK9b6B7bEv","tax_amount":0,"expense_id":""},{"_id":"ac64e02b-219c-4a18-9a7c-191dd5b8f21f","quantity":5,"cost":67,"product_key":"t4","product_cost":0,"notes":"task 4 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":335,"gross_line_total":335,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"qM7e5Rxa2v","tax_amount":0,"expense_id":""},{"_id":"7b6dcee1-7b07-49b7-bcfa-2129ef844f07","quantity":5,"cost":4,"product_key":"t5","product_cost":0,"notes":"task 5 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":20,"gross_line_total":20,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"KGRb4z2eBL","tax_amount":0,"expense_id":""},{"_id":"a8ef31c5-49ac-43f7-a40e-0e311b940589","quantity":5,"cost":11,"product_key":"t6","product_cost":0,"notes":"task 6 description","discount":0,"is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":"0","line_total":55,"gross_line_total":55,"date":"","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","type_id":"2","tax_id":"2","task_id":"GELe3yrb69","tax_amount":0,"expense_id":""}],"entity_type":"invoice","reminder1_sent":"","reminder2_sent":"","reminder3_sent":"","reminder_last_sent":"","paid_to_date":444,"subscription_id":"","auto_bill_enabled":false,"tax_info":{},"invitations":{"data":[{"id":"WJxboZzagw","client_contact_id":"yMYerkEaOB","key":"i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","link":"http:\/\/ninja.test:8000\/client\/invoice\/i6oaEtKOSJGW8ArM7tzz0zWVASYmSebr","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"k8mepZ1bMy","client_contact_id":"gl9av2maG1","key":"H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","link":"http:\/\/ninja.test:8000\/client\/invoice\/H6tz4cLXorbZPJHwF1b08QAZwF7zMQUZ","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""},{"id":"l4zbqQ3bpr","client_contact_id":"7LDdwpRe1Y","key":"viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","link":"http:\/\/ninja.test:8000\/client\/invoice\/viWjxxto5SAr8pUqqgSIdrJbLuAHl3sL","sent_date":"2023-09-27 07:06:09","viewed_date":"","opened_date":"","updated_at":1695798369,"archived_at":0,"created_at":1695798363,"email_status":"","email_error":""}]},"documents":{"data":[]}}}},{"id":"WpmbkrxazJ","user_id":"wMvbmOeYAl","assigned_user_id":"","number":"0048","description":"Blanditiis ad mollitia ratione veritatis.","duration":0,"rate":55,"created_at":1695797987,"updated_at":1695798883,"archived_at":0,"invoice_id":"","client_id":"QJ0dN6dLOv","project_id":"QK9b6nbEvY","is_deleted":false,"time_log":"[[1695761987,1695779987,\"description\",false]]","is_running":false,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","status_id":"kzPdy7aQro","status_sort_order":0,"is_date_based":false,"status_order":null,"date":"2023-09-26","client":{"id":"QJ0dN6dLOv","user_id":"wMvbmOeYAl","assigned_user_id":"","name":"Paucek and Sons","website":"http:\/\/www.wiegand.com\/sit-repellendus-enim-porro-aut-voluptas-voluptates.html","private_notes":"In nihil non voluptas voluptatibus molestiae et. Nihil labore eligendi omnis id. Et cumque reiciendis blanditiis fugiat.","balance":19958.86,"group_settings_id":"","paid_to_date":18895.75,"payment_balance":0,"credit_balance":573.53,"last_login":0,"size_id":"","public_notes":"","client_hash":"ngQe8O6SInYp1D0SKacHE8f6nzr3Gc1UkkoyGMKI","address1":"873","address2":"220 Hand Glen","phone":"","city":"Lake Kallie","state":"Ohio","postal_code":"77890","country_id":"535","industry_id":"","custom_value1":"1974-10-02 21:56:55","custom_value2":"Aqua","custom_value3":"modi","custom_value4":"xhomenick@hotmail.com","shipping_address1":"89064","shipping_address2":"87854 Meda Junction","shipping_city":"South Aryanna","shipping_state":"Connecticut","shipping_postal_code":"52527-1873","shipping_country_id":"4","settings":{"entity":"App\\Models\\Client","industry_id":"","size_id":"","currency_id":"1"},"is_deleted":false,"vat_number":"881403416","id_number":"MU19IWUA7340242407223765691CMM","updated_at":1695811138,"archived_at":0,"created_at":1695796650,"display_name":"Paucek and Sons","number":"0005","has_valid_vat_number":false,"is_tax_exempt":false,"routing_id":"","tax_info":{},"contacts":[{"id":"yMYerkEaOB","first_name":"Bret","last_name":"Beatty","email":"user@example.com","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":true,"is_locked":false,"phone":"1-985-403-1242","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/juMXBqyvDashDUvoYXsdcbZV2SRrFf0BOUFjsc6G"},{"id":"gl9av2maG1","first_name":"Sandra","last_name":"Daniel","email":"linnie.aufderhar@example.net","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"+17319151379","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/sm53aNvvsGUmLXFku0RLPUrP0zLj3rzBcTaGMjHd"},{"id":"7LDdwpRe1Y","first_name":"Leone","last_name":"Bode","email":"ipollich@example.org","created_at":1695796650,"updated_at":1695796650,"archived_at":0,"is_primary":false,"is_locked":false,"phone":"(424) 789-3412","custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","contact_key":"gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma","send_email":true,"last_login":0,"password":"**********","link":"http:\/\/ninja.test:8000\/client\/key_login\/gDUwiOqRehgCHWbbctW8qgKiLmma3xvsZi10a5Ma"}],"documents":{"data":[]},"gateway_tokens":{"data":[]}},"project":{"id":"QK9b6nbEvY","user_id":"wMvbmOeYAl","assigned_user_id":"","client_id":"QJ0dN6dLOv","name":"Linnie Pfannerstill","number":"0001","created_at":1695797987,"updated_at":1695798405,"archived_at":0,"is_deleted":false,"task_rate":97,"due_date":"2023-09-30","private_notes":"These are the private notes for this user.","public_notes":"Quo sed quis reprehenderit est consequatur et.","budgeted_hours":738,"custom_value1":"","custom_value2":"","custom_value3":"","custom_value4":"","color":"#fff","current_hours":0,"documents":{"data":[]}},"invoice":[]}]'; + + public string $invoice_data = '[{"amount":"$6,054.13","balance":"$0.00","balance_raw":"0.000000","number":"0015","discount":1,"po_number":"","date":"20\/Sep\/2023","last_sent_date":"","next_send_date":"","due_date":"","terms":"","public_notes":"","private_notes":"","uses_inclusive_taxes":false,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"total_taxes":"$444.13","total_taxes_raw":"444.130000","is_amount_discount":true,"footer":"","partial":"0.000000","partial_due_date":"","custom_value1":"1984-10-01","custom_value2":"no","custom_value3":"","custom_value4":"","custom_surcharge1":0,"custom_surcharge2":0,"custom_surcharge3":0,"custom_surcharge4":0,"exchange_rate":1,"custom_surcharge_tax1":false,"custom_surcharge_tax2":false,"custom_surcharge_tax3":false,"custom_surcharge_tax4":false,"line_items":[{"quantity":1,"cost":"$935.00","product_key":"Et.","notes":"Illum similique.","discount":"$0.00","is_amount_discount":true,"tax_name1":"Sales Tax","tax_rate1":5,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":0,"line_total":"$935.00","gross_line_total":"$981.75","custom_value1":"https:\/\/picsum.photos\/200","custom_value2":"78","custom_value3":"Itaque laudantium.","custom_value4":"Qui voluptatem ea a.","type_id":"1","product_cost":"$0.00","tax_amount":"$46.75","date":"","tax_id":"","task_id":"","expense_id":"","cost_raw":935,"discount_raw":0,"line_total_raw":935,"gross_line_total_raw":981.75,"tax_amount_raw":46.75,"product_cost_raw":0},{"quantity":1,"cost":"$935.00","product_key":"Et.","notes":"Illum similique.","discount":"$0.00","is_amount_discount":true,"tax_name1":"","tax_rate1":0,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":0,"line_total":"$935.00","gross_line_total":"$935.00","custom_value1":"https:\/\/picsum.photos\/200","custom_value2":"78","custom_value3":"Itaque laudantium.","custom_value4":"Qui voluptatem ea a.","type_id":"1","product_cost":"$0.00","tax_amount":"$0.00","date":"","tax_id":"","task_id":"","expense_id":"","cost_raw":935,"discount_raw":0,"line_total_raw":935,"gross_line_total_raw":935,"tax_amount_raw":0,"product_cost_raw":0},{"quantity":1,"cost":"$935.00","product_key":"Et.","notes":"Illum similique.","discount":"$0.00","is_amount_discount":true,"tax_name1":"GST","tax_rate1":10,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":0,"line_total":"$935.00","gross_line_total":"$1,028.50","custom_value1":"https:\/\/picsum.photos\/200","custom_value2":"78","custom_value3":"Itaque laudantium.","custom_value4":"Qui voluptatem ea a.","type_id":"1","product_cost":"$0.00","tax_amount":"$93.50","date":"","tax_id":"","task_id":"","expense_id":"","cost_raw":935,"discount_raw":0,"line_total_raw":935,"gross_line_total_raw":1028.5,"tax_amount_raw":93.5,"product_cost_raw":0},{"quantity":1,"cost":"$935.00","product_key":"Et.","notes":"Illum similique.","discount":"$0.00","is_amount_discount":true,"tax_name1":"VAT","tax_rate1":17.5,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":0,"line_total":"$935.00","gross_line_total":"$1,098.63","custom_value1":"https:\/\/picsum.photos\/200","custom_value2":"78","custom_value3":"Itaque laudantium.","custom_value4":"Qui voluptatem ea a.","type_id":"1","product_cost":"$0.00","tax_amount":"$163.63","date":"","tax_id":"","task_id":"","expense_id":"","cost_raw":935,"discount_raw":0,"line_total_raw":935,"gross_line_total_raw":1098.63,"tax_amount_raw":163.63,"product_cost_raw":0},{"quantity":1,"cost":"$935.00","product_key":"Et.","notes":"Illum similique.","discount":"$0.00","is_amount_discount":true,"tax_name1":"GST","tax_rate1":10,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":0,"line_total":"$935.00","gross_line_total":"$1,028.50","custom_value1":"https:\/\/picsum.photos\/200","custom_value2":"78","custom_value3":"Itaque laudantium.","custom_value4":"Qui voluptatem ea a.","type_id":"1","product_cost":"$0.00","tax_amount":"$93.50","date":"","tax_id":"","task_id":"","expense_id":"","cost_raw":935,"discount_raw":0,"line_total_raw":935,"gross_line_total_raw":1028.5,"tax_amount_raw":93.5,"product_cost_raw":0},{"quantity":1,"cost":"$935.00","product_key":"Et.","notes":"Illum similique.","discount":"$0.00","is_amount_discount":true,"tax_name1":"Sales Tax","tax_rate1":5,"tax_name2":"","tax_rate2":0,"tax_name3":"","tax_rate3":0,"sort_id":0,"line_total":"$935.00","gross_line_total":"$981.75","custom_value1":"https:\/\/picsum.photos\/200","custom_value2":"78","custom_value3":"Itaque laudantium.","custom_value4":"Qui voluptatem ea a.","type_id":"1","product_cost":"$0.00","tax_amount":"$46.75","date":"","tax_id":"","task_id":"","expense_id":"","cost_raw":935,"discount_raw":0,"line_total_raw":935,"gross_line_total_raw":981.75,"tax_amount_raw":46.75,"product_cost_raw":0}],"reminder1_sent":"","reminder2_sent":"","reminder3_sent":"","reminder_last_sent":"","paid_to_date":"$6,054.13","auto_bill_enabled":false,"client":{"name":"Lowe-Paucek","balance":"38124.670000","payment_balance":"0.000000","credit_balance":"2270.590000"},"payments":[{"status":"Completed","badge":"
+ // | // '. $text .' // | //
Item # | +Description | +Ordered | +Delivered | +Outstanding | +
---|---|---|---|---|
{{ item.product_key }} | +{{ item.notes }} | +{{ item.quantity }} | +{{ item.quantity }} | +0 | +
Item # | +Description | +Ordered | +Delivered | +Outstanding | +
---|---|---|---|---|
{{ item.product_key }} | +{{ item.notes }} | +{{ item.quantity }} | +{{ item.quantity }} | +0 | +
Invoice # | +Date | +Due Date | +Total | +Transaction | +Outstanding | +
---|---|---|---|---|---|
{{ invoice.number }} | +{{ invoice.date }} | +{{ invoice.due_date }} | +{{ invoice.amount }} | ++ | {{ invoice.balance }} | +
{{ payment.number }} | +{{ payment.date }} | ++ | + {% if pivot.amount_raw > 0 %} + {{ pivot.amount }} - {{ payment.type.name }} + {% else %} + ({{ pivot.refunded }}) + {% endif %} + | ++ | + |