mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'v5-develop' into v5-stable
This commit is contained in:
commit
3ecc85903c
@ -58,3 +58,6 @@ DELETE_BACKUP_DAYS=60
|
||||
|
||||
COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
|
||||
SENTRY_LARAVEL_DSN=https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co/5
|
||||
|
||||
GOOGLE_PLAY_PACKAGE_NAME=
|
||||
APPSTORE_PASSWORD=
|
||||
|
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@ -39,6 +39,19 @@ jobs:
|
||||
sudo find ./vendor/bin/ -type f -exec chmod +x {} \;
|
||||
sudo find ./ -type d -exec chmod 755 {} \;
|
||||
|
||||
- name: Prepare React FrontEnd
|
||||
run: |
|
||||
mkdir public/react
|
||||
git clone https://${{secrets.commit_secret}}@github.com/invoiceninja/ui.git
|
||||
cd ui
|
||||
git checkout main
|
||||
npm i
|
||||
npm run build
|
||||
cp -r dist/react/* ../public/react
|
||||
cd ..
|
||||
rm -rf ui
|
||||
php artisan ninja:react
|
||||
|
||||
- name: Prepare JS/CSS assets
|
||||
run: |
|
||||
npm i
|
||||
|
@ -1 +1 @@
|
||||
5.3.90
|
||||
5.3.99
|
@ -74,7 +74,7 @@ class CheckData extends Command
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:check-data {--database=} {--fix=} {--client_id=} {--vendor_id=} {--paid_to_date=} {--client_balance=} {--ledger_balance=}';
|
||||
protected $signature = 'ninja:check-data {--database=} {--fix=} {--client_id=} {--vendor_id=} {--paid_to_date=} {--client_balance=} {--ledger_balance=} {--balance_status=}';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -89,6 +89,9 @@ class CheckData extends Command
|
||||
|
||||
protected $wrong_balances = 0;
|
||||
|
||||
protected $wrong_paid_status = 0;
|
||||
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$time_start = microtime(true);
|
||||
@ -109,6 +112,7 @@ class CheckData extends Command
|
||||
$this->checkVendorContacts();
|
||||
$this->checkEntityInvitations();
|
||||
$this->checkCompanyData();
|
||||
$this->checkBalanceVsPaidStatus();
|
||||
|
||||
if(Ninja::isHosted())
|
||||
$this->checkAccountStatuses();
|
||||
@ -856,4 +860,45 @@ class CheckData extends Command
|
||||
});
|
||||
}
|
||||
|
||||
public function checkBalanceVsPaidStatus()
|
||||
{
|
||||
$this->wrong_paid_status = 0;
|
||||
|
||||
foreach(Invoice::with(['payments'])->whereHas('payments')->where('status_id', 4)->where('balance', '>', 0)->where('is_deleted',0)->cursor() as $invoice)
|
||||
{
|
||||
$this->$this->wrong_paid_status++;
|
||||
|
||||
$this->logMessage("# {$invoice->id} " . ' - '.$invoice->number." - Marked as paid, but balance = {$invoice->balance}");
|
||||
|
||||
if($this->option('balance_status')){
|
||||
|
||||
$val = $invoice->balance;
|
||||
|
||||
$invoice->balance = 0;
|
||||
$invoice->paid_to_date=$val;
|
||||
$invoice->save();
|
||||
|
||||
$p = $invoice->payments->first();
|
||||
|
||||
if($p && (int)$p->amount == 0)
|
||||
{
|
||||
$p->amount = $val;
|
||||
$p->applied = $val;
|
||||
$p->save();
|
||||
|
||||
$pivot = $p->paymentables->first();
|
||||
$pivot->amount = $val;
|
||||
$pivot->save();
|
||||
}
|
||||
|
||||
|
||||
$this->logMessage("Fixing {$invoice->id} settings payment to {$val}");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->logMessage($this->wrong_paid_status." wrong invoices with bad balance state");
|
||||
|
||||
}
|
||||
}
|
@ -108,6 +108,7 @@ class CreateSingleAccount extends Command
|
||||
'default_password_timeout' => 30*60000,
|
||||
'portal_mode' => 'domain',
|
||||
'portal_domain' => 'http://ninja.test:8000',
|
||||
'track_inventory' => true
|
||||
]);
|
||||
|
||||
$settings = $company->settings;
|
||||
|
88
app/Console/Commands/ReactBuilder.php
Normal file
88
app/Console/Commands/ReactBuilder.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Backup;
|
||||
use App\Models\Design;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use stdClass;
|
||||
|
||||
class ReactBuilder extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:react';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Builds blade component for react includes';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$includes = '';
|
||||
|
||||
$directoryIterator = new \RecursiveDirectoryIterator(public_path('react'), \RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
|
||||
foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) {
|
||||
|
||||
if(str_contains($file->getFileName(), '.js')) {
|
||||
|
||||
if(str_contains($file->getFileName(), 'index.')){
|
||||
|
||||
$includes .= '<script type="module" crossorigin src="/react/' . $file->getFileName() . '"></script>'."\n";
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
$includes .= '<link rel="modulepreload" href="/react/' . $file->getFileName() . '">'."\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(str_contains($file->getFileName(), '.css')) {
|
||||
|
||||
$includes .= '<link rel="stylesheet" href="/react/' . $file->getFileName() . '">'."\n";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
file_put_contents(resource_path('views/react/head.blade.php'), $includes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -20,6 +20,7 @@ use App\Jobs\Ninja\AdjustEmailQuota;
|
||||
use App\Jobs\Ninja\CompanySizeCheck;
|
||||
use App\Jobs\Ninja\QueueSize;
|
||||
use App\Jobs\Ninja\SystemMaintenance;
|
||||
use App\Jobs\Ninja\TaskScheduler;
|
||||
use App\Jobs\Util\DiskCleanup;
|
||||
use App\Jobs\Util\ReminderJob;
|
||||
use App\Jobs\Util\SchedulerCheck;
|
||||
@ -73,11 +74,12 @@ class Kernel extends ConsoleKernel
|
||||
|
||||
$schedule->job(new SchedulerCheck)->daily()->withoutOverlapping();
|
||||
|
||||
$schedule->job(new TaskScheduler())->daily()->withoutOverlapping();
|
||||
|
||||
$schedule->job(new SystemMaintenance)->weekly()->withoutOverlapping();
|
||||
|
||||
if(Ninja::isSelfHost())
|
||||
{
|
||||
|
||||
$schedule->call(function () {
|
||||
Account::whereNotNull('id')->update(['is_scheduler_running' => true]);
|
||||
})->everyFiveMinutes();
|
||||
@ -99,9 +101,9 @@ class Kernel extends ConsoleKernel
|
||||
|
||||
}
|
||||
|
||||
if(config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled') && !config('ninja.is_docker')) {
|
||||
if (config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled') && !config('ninja.is_docker')) {
|
||||
|
||||
$schedule->command('queue:work database --stop-when-empty')->everyMinute()->withoutOverlapping();
|
||||
$schedule->command('queue:work database --stop-when-empty --memory=256')->everyMinute()->withoutOverlapping();
|
||||
|
||||
$schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping();
|
||||
|
||||
@ -116,7 +118,7 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function commands()
|
||||
{
|
||||
$this->load(__DIR__.'/Commands');
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
|
@ -116,6 +116,9 @@ class CompanySettings extends BaseSettings
|
||||
public $project_number_pattern = ''; //@implemented
|
||||
public $project_number_counter = 1; //@implemented
|
||||
|
||||
public $purchase_order_number_pattern = ''; //@implemented
|
||||
public $purchase_order_number_counter = 1; //@implemented
|
||||
|
||||
public $shared_invoice_quote_counter = false; //@implemented
|
||||
public $shared_invoice_credit_counter = false; //@implemented
|
||||
public $recurring_number_prefix = ''; //@implemented
|
||||
@ -133,6 +136,13 @@ class CompanySettings extends BaseSettings
|
||||
public $invoice_design_id = 'Wpmbk5ezJn'; //@implemented
|
||||
public $quote_design_id = 'Wpmbk5ezJn'; //@implemented
|
||||
public $credit_design_id = 'Wpmbk5ezJn'; //@implemented
|
||||
|
||||
public $purchase_order_design_id = 'Wpmbk5ezJn';
|
||||
public $purchase_order_footer = ''; //@implemented
|
||||
public $purchase_order_terms = ''; //@implemented
|
||||
public $purchase_order_public_notes = ''; //@implemented
|
||||
public $require_purchase_order_signature = false; //@TODO ben to confirm
|
||||
|
||||
public $invoice_footer = ''; //@implemented
|
||||
public $credit_footer = ''; //@implemented
|
||||
public $credit_terms = ''; //@implemented
|
||||
@ -170,6 +180,8 @@ class CompanySettings extends BaseSettings
|
||||
public $email_subject_payment = ''; //@implemented
|
||||
public $email_subject_payment_partial = ''; //@implemented
|
||||
public $email_subject_statement = ''; //@implemented
|
||||
public $email_subject_purchase_order = ''; //@implemented
|
||||
public $email_template_purchase_order = ''; //@implemented
|
||||
public $email_template_invoice = ''; //@implemented
|
||||
public $email_template_credit = ''; //@implemented
|
||||
public $email_template_quote = ''; //@implemented
|
||||
@ -249,6 +261,9 @@ class CompanySettings extends BaseSettings
|
||||
public $primary_color = '#298AAB';
|
||||
public $secondary_color = '#7081e0';
|
||||
|
||||
public $page_numbering = false;
|
||||
public $page_numbering_alignment = 'C'; //C,R,L
|
||||
|
||||
public $hide_paid_to_date = false; //@TODO where?
|
||||
public $embed_documents = false; //@TODO where?
|
||||
public $all_pages_header = false; //@deprecated 31-05-2021
|
||||
@ -274,6 +289,17 @@ class CompanySettings extends BaseSettings
|
||||
public $auto_archive_invoice_cancelled = false;
|
||||
|
||||
public static $casts = [
|
||||
'email_subject_purchase_order' => 'string',
|
||||
'email_template_purchase_order' => 'string',
|
||||
'require_purchase_order_signature' => 'bool',
|
||||
'purchase_order_public_notes' => 'string',
|
||||
'purchase_order_terms' => 'string',
|
||||
'purchase_order_design_id' => 'string',
|
||||
'purchase_order_footer' => 'string',
|
||||
'purchase_order_number_pattern' => 'string',
|
||||
'purchase_order_number_counter' => 'int',
|
||||
'page_numbering_alignment' => 'string',
|
||||
'page_numbering' => 'bool',
|
||||
'auto_archive_invoice_cancelled' => 'bool',
|
||||
'email_from_name' => 'string',
|
||||
'show_all_tasks_client_portal' => 'string',
|
||||
@ -469,6 +495,7 @@ class CompanySettings extends BaseSettings
|
||||
'portal_custom_footer' => 'string',
|
||||
'portal_custom_js' => 'string',
|
||||
'client_portal_enable_uploads' => 'bool',
|
||||
'purchase_order_number_counter' => 'integer',
|
||||
];
|
||||
|
||||
public static $free_plan_casts = [
|
||||
@ -522,6 +549,7 @@ class CompanySettings extends BaseSettings
|
||||
'invoice_design_id',
|
||||
'quote_design_id',
|
||||
'credit_design_id',
|
||||
'purchase_order_design_id',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -620,6 +648,25 @@ class CompanySettings extends BaseSettings
|
||||
'$client.phone',
|
||||
'$contact.email',
|
||||
],
|
||||
'vendor_details' => [
|
||||
'$vendor.name',
|
||||
'$vendor.number',
|
||||
'$vendor.vat_number',
|
||||
'$vendor.address1',
|
||||
'$vendor.address2',
|
||||
'$vendor.city_state_postal',
|
||||
'$vendor.country',
|
||||
'$vendor.phone',
|
||||
'$contact.email',
|
||||
],
|
||||
'purchase_order_details' => [
|
||||
'$purchase_order.number',
|
||||
'$purchase_order.po_number',
|
||||
'$purchase_order.date',
|
||||
'$purchase_order.due_date',
|
||||
'$purchase_order.total',
|
||||
'$purchase_order.balance_due',
|
||||
],
|
||||
'company_details' => [
|
||||
'$company.name',
|
||||
'$company.id_number',
|
||||
|
@ -61,10 +61,13 @@ class EmailTemplateDefaults
|
||||
break;
|
||||
case 'email_template_custom3':
|
||||
return self::emailInvoiceTemplate();
|
||||
case 'email_template_purchase_order':
|
||||
return self::emailPurchaseOrderTemplate();
|
||||
break;
|
||||
|
||||
/* Subject */
|
||||
|
||||
case 'email_subject_purchase_order':
|
||||
return self::emailPurchaseOrderSubject();
|
||||
case 'email_subject_invoice':
|
||||
return self::emailInvoiceSubject();
|
||||
break;
|
||||
@ -152,6 +155,20 @@ class EmailTemplateDefaults
|
||||
return ctrans('texts.payment_subject');
|
||||
}
|
||||
|
||||
public static function emailPurchaseOrderSubject()
|
||||
{
|
||||
return ctrans('texts.purchase_order_subject', ['number' => '$number', 'account' => '$account']);
|
||||
}
|
||||
|
||||
public static function emailPurchaseOrderTemplate()
|
||||
{
|
||||
|
||||
$purchase_order_message = '<p>$vendor<br><br>'.self::transformText('purchase_order_message').'</p><div class="center">$view_button</div>';
|
||||
|
||||
return $purchase_order_message;
|
||||
|
||||
}
|
||||
|
||||
public static function emailPaymentTemplate()
|
||||
{
|
||||
$payment_message = '<p>$client<br><br>'.self::transformText('payment_message').'<br><br>$invoices</p><div class="center">$view_button</div>';
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace App\Events\Invoice;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
@ -35,12 +34,12 @@ class InvoiceWasEmailedAndFailed
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param InvoiceInvitation $invitation
|
||||
* @param $invitation
|
||||
* @param Company $company
|
||||
* @param string $errors
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(InvoiceInvitation $invitation, Company $company, string $message, string $template, array $event_vars)
|
||||
public function __construct($invitation, Company $company, string $message, string $template, array $event_vars)
|
||||
{
|
||||
$this->invitation = $invitation;
|
||||
|
||||
|
47
app/Events/PurchaseOrder/PurchaseOrderWasArchived.php
Normal file
47
app/Events/PurchaseOrder/PurchaseOrderWasArchived.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasArchived.
|
||||
*/
|
||||
class PurchaseOrderWasArchived
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var PurchaseOrder
|
||||
*/
|
||||
public $purchase_order;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
47
app/Events/PurchaseOrder/PurchaseOrderWasCreated.php
Normal file
47
app/Events/PurchaseOrder/PurchaseOrderWasCreated.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasCreated.
|
||||
*/
|
||||
class PurchaseOrderWasCreated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var PurchaseOrder
|
||||
*/
|
||||
public $purchase_order;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
47
app/Events/PurchaseOrder/PurchaseOrderWasDeleted.php
Normal file
47
app/Events/PurchaseOrder/PurchaseOrderWasDeleted.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasDeleted.
|
||||
*/
|
||||
class PurchaseOrderWasDeleted
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var PurchaseOrder
|
||||
*/
|
||||
public $purchase_order;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
48
app/Events/PurchaseOrder/PurchaseOrderWasEmailed.php
Normal file
48
app/Events/PurchaseOrder/PurchaseOrderWasEmailed.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\PurchaseOrderInvitation;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasEmailed.
|
||||
*/
|
||||
class PurchaseOrderWasEmailed
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var PurchaseOrder
|
||||
*/
|
||||
public $invitation;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrderInvitation $invitation, Company $company, array $event_vars)
|
||||
{
|
||||
$this->invitation = $invitation;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
49
app/Events/PurchaseOrder/PurchaseOrderWasRestored.php
Normal file
49
app/Events/PurchaseOrder/PurchaseOrderWasRestored.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasRestored.
|
||||
*/
|
||||
class PurchaseOrderWasRestored
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var PurchaseOrder
|
||||
*/
|
||||
public $purchase_order;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
public $fromDeleted;
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, $fromDeleted, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->fromDeleted = $fromDeleted;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
47
app/Events/PurchaseOrder/PurchaseOrderWasUpdated.php
Normal file
47
app/Events/PurchaseOrder/PurchaseOrderWasUpdated.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasUpdated.
|
||||
*/
|
||||
class PurchaseOrderWasUpdated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var PurchaseOrder
|
||||
*/
|
||||
public $purchase_order;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
47
app/Events/PurchaseOrder/PurchaseOrderWasViewed.php
Normal file
47
app/Events/PurchaseOrder/PurchaseOrderWasViewed.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\PurchaseOrder;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class PurchaseOrderWasViewed.
|
||||
*/
|
||||
class PurchaseOrderWasViewed
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var PurchaseOrder
|
||||
*/
|
||||
public $purchase_order;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, array $event_vars)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
@ -78,7 +78,7 @@ class QuoteItemExport extends BaseExport
|
||||
'tax_name2' => 'item.tax_name2',
|
||||
'tax_name3' => 'item.tax_name3',
|
||||
'line_total' => 'item.line_total',
|
||||
'gross_line_total' => 'item.gross_line_total',
|
||||
// 'gross_line_total' => 'item.gross_line_total',
|
||||
'custom_value1' => 'item.custom_value1',
|
||||
'custom_value2' => 'item.custom_value2',
|
||||
'custom_value3' => 'item.custom_value3',
|
||||
|
56
app/Factory/PurchaseOrderFactory.php
Normal file
56
app/Factory/PurchaseOrderFactory.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\PurchaseOrder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PurchaseOrderFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id, object $settings = null, Client $client = null) :PurchaseOrder
|
||||
{
|
||||
$purchase_order = new PurchaseOrder();
|
||||
$purchase_order->status_id = PurchaseOrder::STATUS_DRAFT;
|
||||
$purchase_order->number = null;
|
||||
$purchase_order->discount = 0;
|
||||
$purchase_order->is_amount_discount = true;
|
||||
$purchase_order->po_number = '';
|
||||
$purchase_order->footer = '';
|
||||
$purchase_order->terms = '';
|
||||
$purchase_order->public_notes = '';
|
||||
$purchase_order->private_notes = '';
|
||||
$purchase_order->date = now()->format('Y-m-d');
|
||||
$purchase_order->due_date = null;
|
||||
$purchase_order->partial_due_date = null;
|
||||
$purchase_order->is_deleted = false;
|
||||
$purchase_order->line_items = json_encode([]);
|
||||
$purchase_order->tax_name1 = '';
|
||||
$purchase_order->tax_rate1 = 0;
|
||||
$purchase_order->tax_name2 = '';
|
||||
$purchase_order->tax_rate2 = 0;
|
||||
$purchase_order->tax_name3 = '';
|
||||
$purchase_order->tax_rate3 = 0;
|
||||
$purchase_order->custom_value1 = '';
|
||||
$purchase_order->custom_value2 = '';
|
||||
$purchase_order->custom_value3 = '';
|
||||
$purchase_order->custom_value4 = '';
|
||||
$purchase_order->amount = 0;
|
||||
$purchase_order->balance = 0;
|
||||
$purchase_order->partial = 0;
|
||||
$purchase_order->user_id = $user_id;
|
||||
$purchase_order->company_id = $company_id;
|
||||
$purchase_order->recurring_id = null;
|
||||
|
||||
return $purchase_order;
|
||||
}
|
||||
}
|
31
app/Factory/PurchaseOrderInvitationFactory.php
Normal file
31
app/Factory/PurchaseOrderInvitationFactory.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\PurchaseOrderInvitation;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PurchaseOrderInvitationFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :PurchaseOrderInvitation
|
||||
{
|
||||
$ci = new PurchaseOrderInvitation();
|
||||
$ci->company_id = $company_id;
|
||||
$ci->user_id = $user_id;
|
||||
$ci->vendor_contact_id = null;
|
||||
$ci->purchase_order_id = null;
|
||||
$ci->key = Str::random(config('ninja.key_length'));
|
||||
$ci->transaction_reference = null;
|
||||
$ci->message_id = null;
|
||||
$ci->email_error = '';
|
||||
$ci->signature_base64 = '';
|
||||
$ci->signature_date = null;
|
||||
$ci->sent_date = null;
|
||||
$ci->viewed_date = null;
|
||||
$ci->opened_date = null;
|
||||
|
||||
return $ci;
|
||||
}
|
||||
}
|
@ -48,6 +48,7 @@ class RecurringInvoiceFactory
|
||||
$invoice->frequency_id = RecurringInvoice::FREQUENCY_MONTHLY;
|
||||
$invoice->last_sent_date = null;
|
||||
$invoice->next_send_date = null;
|
||||
$invoice->next_send_date_client = null;
|
||||
$invoice->remaining_cycles = -1;
|
||||
$invoice->paid_to_date = 0;
|
||||
$invoice->auto_bill_enabled = false;
|
||||
|
@ -49,7 +49,7 @@ class CreditFilters extends QueryFilters
|
||||
}
|
||||
|
||||
if (in_array('partial', $status_parameters)) {
|
||||
$this->builder->where('status_id', Credit::STAUTS_PARTIAL);
|
||||
$this->builder->where('status_id', Credit::STATUS_PARTIAL);
|
||||
}
|
||||
|
||||
if (in_array('applied', $status_parameters)) {
|
||||
|
185
app/Filters/PurchaseOrderFilters.php
Normal file
185
app/Filters/PurchaseOrderFilters.php
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
|
||||
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class PurchaseOrderFilters extends QueryFilters
|
||||
{
|
||||
/**
|
||||
* Filter based on client status.
|
||||
*
|
||||
* Statuses we need to handle
|
||||
* - all
|
||||
* - paid
|
||||
* - unpaid
|
||||
* - overdue
|
||||
* - reversed
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
public function credit_status(string $value = '') :Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$status_parameters = explode(',', $value);
|
||||
|
||||
if (in_array('all', $status_parameters)) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
if (in_array('draft', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_DRAFT);
|
||||
}
|
||||
|
||||
if (in_array('partial', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_PARTIAL);
|
||||
}
|
||||
|
||||
if (in_array('applied', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_APPLIED);
|
||||
}
|
||||
|
||||
//->where('due_date', '>', Carbon::now())
|
||||
//->orWhere('partial_due_date', '>', Carbon::now());
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function filter(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('purchase_orders.number', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.number', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.date', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.amount', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.balance', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.custom_value1', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.custom_value2', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.custom_value3', 'like', '%'.$filter.'%')
|
||||
->orWhere('purchase_orders.custom_value4', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted - legacy from V1.
|
||||
*
|
||||
* @param string filter
|
||||
* @return Builder
|
||||
*/
|
||||
public function status(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$table = 'purchase_orders';
|
||||
$filters = explode(',', $filter);
|
||||
|
||||
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||
$query->whereNull($table.'.id');
|
||||
|
||||
if (in_array(parent::STATUS_ACTIVE, $filters)) {
|
||||
$query->orWhereNull($table.'.deleted_at');
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
|
||||
$query->orWhere(function ($query) use ($table) {
|
||||
$query->whereNotNull($table.'.deleted_at');
|
||||
|
||||
if (! in_array($table, ['users'])) {
|
||||
$query->where($table.'.is_deleted', '=', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_DELETED, $filters)) {
|
||||
$query->orWhere($table.'.is_deleted', '=', 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort) : Builder
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base query.
|
||||
*
|
||||
* @param int company_id
|
||||
* @param User $user
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function baseQuery(int $company_id, User $user) : Builder
|
||||
{
|
||||
// ..
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the query by the users company ID.
|
||||
*
|
||||
* We need to ensure we are using the correct company ID
|
||||
* as we could be hitting this from either the client or company auth guard
|
||||
*
|
||||
*/
|
||||
public function entityFilter()
|
||||
{
|
||||
if (auth()->guard('contact')->user()) {
|
||||
return $this->contactViewFilter();
|
||||
} else {
|
||||
return $this->builder->company();
|
||||
}
|
||||
|
||||
// return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* We need additional filters when showing purchase orders for the
|
||||
* client portal. Need to automatically exclude drafts and cancelled purchase orders.
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
private function contactViewFilter() : Builder
|
||||
{
|
||||
return $this->builder
|
||||
->whereCompanyId(auth()->guard('contact')->user()->company->id)
|
||||
->whereNotIn('status_id', [PurchaseOrder::STATUS_DRAFT]);
|
||||
}
|
||||
}
|
@ -81,7 +81,7 @@ abstract class QueryFilters
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen($value)) {
|
||||
if (is_string($value) && strlen($value)) {
|
||||
$this->$name($value);
|
||||
} else {
|
||||
$this->$name();
|
||||
|
@ -52,7 +52,10 @@ class InvoiceItemSum
|
||||
|
||||
$this->invoice = $invoice;
|
||||
|
||||
if($this->invoice->client)
|
||||
$this->currency = $this->invoice->client->currency();
|
||||
else
|
||||
$this->currency = $this->invoice->vendor->currency();
|
||||
|
||||
$this->line_items = [];
|
||||
}
|
||||
|
@ -46,7 +46,10 @@ class InvoiceItemSumInclusive
|
||||
|
||||
$this->invoice = $invoice;
|
||||
|
||||
if($this->invoice->client)
|
||||
$this->currency = $this->invoice->client->currency();
|
||||
else
|
||||
$this->currency = $this->invoice->vendor->currency();
|
||||
|
||||
$this->line_items = [];
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ class InvoiceSum
|
||||
|
||||
private $gross_sub_total;
|
||||
|
||||
private $precision;
|
||||
|
||||
/**
|
||||
* Constructs the object with Invoice and Settings object.
|
||||
*
|
||||
@ -53,8 +55,10 @@ class InvoiceSum
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
|
||||
// if(!$this->invoice->relationLoaded('client'))
|
||||
// $this->invoice->load('client');
|
||||
if($this->invoice->client)
|
||||
$this->precision = $this->invoice->client->currency()->precision;
|
||||
else
|
||||
$this->precision = $this->invoice->vendor->currency()->precision;
|
||||
|
||||
$this->tax_map = new Collection;
|
||||
}
|
||||
@ -224,11 +228,19 @@ class InvoiceSum
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
public function getPurchaseOrder()
|
||||
{
|
||||
$this->setCalculatedAttributes();
|
||||
$this->invoice->saveQuietly();
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
public function getRecurringInvoice()
|
||||
{
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
||||
$this->invoice->total_taxes = $this->getTotalTaxes();
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision);
|
||||
|
||||
$this->invoice->saveQuietly();
|
||||
|
||||
@ -247,13 +259,13 @@ class InvoiceSum
|
||||
if ($this->invoice->amount != $this->invoice->balance) {
|
||||
$paid_to_date = $this->invoice->amount - $this->invoice->balance;
|
||||
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision) - $paid_to_date;
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision) - $paid_to_date;
|
||||
} else {
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision);
|
||||
}
|
||||
}
|
||||
/* Set new calculated total */
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
||||
|
||||
$this->invoice->total_taxes = $this->getTotalTaxes();
|
||||
|
||||
|
@ -41,6 +41,7 @@ class InvoiceSumInclusive
|
||||
|
||||
private $sub_total;
|
||||
|
||||
private $precision;
|
||||
/**
|
||||
* Constructs the object with Invoice and Settings object.
|
||||
*
|
||||
@ -50,6 +51,11 @@ class InvoiceSumInclusive
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
|
||||
if($this->invoice->client)
|
||||
$this->precision = $this->invoice->client->currency()->precision;
|
||||
else
|
||||
$this->precision = $this->invoice->vendor->currency()->precision;
|
||||
|
||||
$this->tax_map = new Collection;
|
||||
}
|
||||
|
||||
@ -164,32 +170,15 @@ class InvoiceSumInclusive
|
||||
|
||||
private function calculateTotals()
|
||||
{
|
||||
//$this->total += $this->total_taxes;
|
||||
|
||||
// if (is_numeric($this->invoice->custom_value1)) {
|
||||
// $this->total += $this->invoice->custom_value1;
|
||||
// }
|
||||
|
||||
// if (is_numeric($this->invoice->custom_value2)) {
|
||||
// $this->total += $this->invoice->custom_value2;
|
||||
// }
|
||||
|
||||
// if (is_numeric($this->invoice->custom_value3)) {
|
||||
// $this->total += $this->invoice->custom_value3;
|
||||
// }
|
||||
|
||||
// if (is_numeric($this->invoice->custom_value4)) {
|
||||
// $this->total += $this->invoice->custom_value4;
|
||||
// }
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRecurringInvoice()
|
||||
{
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
||||
$this->invoice->total_taxes = $this->getTotalTaxes();
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision);
|
||||
|
||||
$this->invoice->saveQuietly();
|
||||
|
||||
@ -229,6 +218,15 @@ class InvoiceSumInclusive
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
public function getPurchaseOrder()
|
||||
{
|
||||
//Build invoice values here and return Invoice
|
||||
$this->setCalculatedAttributes();
|
||||
$this->invoice->saveQuietly();
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build $this->invoice variables after
|
||||
* calculations have been performed.
|
||||
@ -240,14 +238,14 @@ class InvoiceSumInclusive
|
||||
if ($this->invoice->amount != $this->invoice->balance) {
|
||||
$paid_to_date = $this->invoice->amount - $this->invoice->balance;
|
||||
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision) - $paid_to_date;
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision) - $paid_to_date;
|
||||
} else {
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set new calculated total */
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
|
||||
|
||||
$this->invoice->total_taxes = $this->getTotalTaxes();
|
||||
|
||||
|
@ -17,6 +17,7 @@ use App\Transformers\ActivityTransformer;
|
||||
use App\Utils\HostedPDF\NinjaPdf;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\PhantomJS\Phantom;
|
||||
use App\Utils\Traits\Pdf\PageNumbering;
|
||||
use App\Utils\Traits\Pdf\PdfMaker;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@ -27,7 +28,7 @@ use stdClass;
|
||||
|
||||
class ActivityController extends BaseController
|
||||
{
|
||||
use PdfMaker;
|
||||
use PdfMaker, PageNumbering;
|
||||
|
||||
protected $entity_type = Activity::class;
|
||||
|
||||
@ -90,6 +91,33 @@ class ActivityController extends BaseController
|
||||
$activities = Activity::orderBy('created_at', 'DESC')->company()
|
||||
->take($default_activities);
|
||||
|
||||
if($request->has('react')){
|
||||
|
||||
$system = ctrans('texts.system');
|
||||
|
||||
$data = $activities->cursor()->map(function ($activity) use($system){
|
||||
|
||||
$arr=
|
||||
[
|
||||
'client' => $activity->client ? $activity->client : '',
|
||||
'contact' => $activity->contact ? $activity->contact : '',
|
||||
'quote' => $activity->quote ? $activity->quote : '',
|
||||
'user' => $activity->user ? $activity->user : '',
|
||||
'expense' => $activity->expense ? $activity->expense : '',
|
||||
'invoice' => $activity->invoice ? $activity->invoice : '',
|
||||
'recurring_invoice' => $activity->recurring_invoice ? $activity->recurring_invoice : '',
|
||||
'payment' => $activity->payment ? $activity->payment : '',
|
||||
'credit' => $activity->credit ? $activity->credit : '',
|
||||
'task' => $activity->task ? $activity->task : '',
|
||||
];
|
||||
|
||||
return array_merge($arr, $activity->toArray());
|
||||
|
||||
});
|
||||
|
||||
return response()->json(['data' => $data->toArray()], 200);
|
||||
}
|
||||
|
||||
return $this->listResponse($activities);
|
||||
}
|
||||
|
||||
@ -164,12 +192,35 @@ class ActivityController extends BaseController
|
||||
|
||||
if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') {
|
||||
$pdf = (new Phantom)->convertHtmlToPdf($html_backup);
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, $activity->company);
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
|
||||
}
|
||||
elseif(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){
|
||||
$pdf = (new NinjaPdf())->build($html_backup);
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, $activity->company);
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
$pdf = $this->makePdf(null, null, $html_backup);
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, $activity->company);
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (isset($activity->invoice_id)) {
|
||||
|
@ -780,6 +780,9 @@ class BaseController extends Controller
|
||||
|
||||
$this->buildCache();
|
||||
|
||||
if(config('ninja.react_app_enabled'))
|
||||
return response()->view('react.index', $data)->header('X-Frame-Options', 'SAMEORIGIN', false);
|
||||
else
|
||||
return response()->view('index.index', $data)->header('X-Frame-Options', 'SAMEORIGIN', false);
|
||||
|
||||
}
|
||||
|
@ -154,8 +154,10 @@ class EntityViewController extends Controller
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ 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\CurlUtils;
|
||||
@ -128,8 +129,10 @@ class InvitationController extends Controller
|
||||
if (auth()->guard('contact')->user() && ! request()->has('silent') && ! $invitation->viewed_date) {
|
||||
$invitation->markViewed();
|
||||
|
||||
if(!session()->get('is_silent'))
|
||||
event(new InvitationWasViewed($invitation->{$entity}, $invitation, $invitation->{$entity}->company, Ninja::eventVars()));
|
||||
|
||||
if(!session()->get('is_silent'))
|
||||
$this->fireEntityViewedEvent($invitation, $entity);
|
||||
}
|
||||
else{
|
||||
@ -191,7 +194,6 @@ class InvitationController extends Controller
|
||||
return response()->json(["message" => "no record found"], 400);
|
||||
|
||||
$file_name = $invitation->{$entity}->numberFormatter().'.pdf';
|
||||
nlog($file_name);
|
||||
|
||||
$file = CreateRawPdf::dispatchNow($invitation, $invitation->company->db);
|
||||
|
||||
@ -280,6 +282,10 @@ class InvitationController extends Controller
|
||||
$invite = CreditInvitation::withTrashed()->where('key', $invitation_key)->first();
|
||||
$invite->contact->send_email = false;
|
||||
$invite->contact->save();
|
||||
}elseif($entity == 'purchase_order'){
|
||||
$invite = PurchaseOrderInvitation::withTrashed()->where('key', $invitation_key)->first();
|
||||
$invite->contact->send_email = false;
|
||||
$invite->contact->save();
|
||||
}
|
||||
else
|
||||
return abort(404);
|
||||
|
@ -61,7 +61,7 @@ class InvoiceController extends Controller
|
||||
|
||||
$invitation = $invoice->invitations()->where('client_contact_id', auth()->guard('contact')->user()->id)->first();
|
||||
|
||||
if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) {
|
||||
if ($invitation && auth()->guard('contact') && !session()->get('is_silent') && ! $invitation->viewed_date) {
|
||||
|
||||
$invitation->markViewed();
|
||||
|
||||
|
@ -125,13 +125,14 @@ class NinjaPlanController extends Controller
|
||||
$gateway_driver->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]);
|
||||
|
||||
//set free trial
|
||||
// $account = auth()->guard('contact')->user()->company->account;
|
||||
if(auth()->guard('contact')->user()->client->custom_value2){
|
||||
MultiDB::findAndSetDbByAccountKey(auth()->guard('contact')->user()->client->custom_value2);
|
||||
$account = Account::where('key', auth()->guard('contact')->user()->client->custom_value2)->first();
|
||||
$account->trial_started = now();
|
||||
$account->trial_plan = 'pro';
|
||||
// $account->trial_started = now();
|
||||
// $account->trial_plan = 'pro';
|
||||
$account->plan = 'pro';
|
||||
$account->plan_term = 'month';
|
||||
$account->plan_started = now();
|
||||
$account->plan_expires = now()->addDays(14);
|
||||
$account->save();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest;
|
||||
use App\Jobs\Util\ApplePayDomain;
|
||||
use App\Models\Client;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\PaymentDrivers\Stripe\Jobs\StripeWebhook;
|
||||
use App\Repositories\CompanyRepository;
|
||||
use App\Transformers\CompanyGatewayTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
@ -212,6 +213,11 @@ class CompanyGatewayController extends BaseController
|
||||
|
||||
ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
|
||||
|
||||
if(in_array($company_gateway->gateway_key, $this->stripe_keys))
|
||||
{
|
||||
StripeWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
|
||||
}
|
||||
|
||||
return $this->itemResponse($company_gateway);
|
||||
}
|
||||
|
||||
|
@ -220,13 +220,12 @@ class InvoiceController extends BaseController
|
||||
public function store(StoreInvoiceRequest $request)
|
||||
{
|
||||
|
||||
// $client = Client::find($request->input('client_id'));
|
||||
|
||||
$invoice = $this->invoice_repo->save($request->all(), InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
$invoice = $invoice->service()
|
||||
->fillDefaults()
|
||||
->triggeredActions($request)
|
||||
->adjustInventory()
|
||||
->save();
|
||||
|
||||
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
@ -416,9 +415,14 @@ class InvoiceController extends BaseController
|
||||
return response()->json(['message' => ctrans('texts.locked_invoice')], 403);
|
||||
}
|
||||
|
||||
$old_invoice = $invoice->line_items;
|
||||
|
||||
$invoice = $this->invoice_repo->save($request->all(), $invoice);
|
||||
|
||||
$invoice->service()->triggeredActions($request)->touchPdf();
|
||||
$invoice->service()
|
||||
->triggeredActions($request)
|
||||
->touchPdf()
|
||||
->adjustInventory($old_invoice);
|
||||
|
||||
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
@ -711,7 +715,6 @@ class InvoiceController extends BaseController
|
||||
echo Storage::get($file);
|
||||
}, basename($file), ['Content-Type' => 'application/pdf']);
|
||||
|
||||
|
||||
break;
|
||||
case 'restore':
|
||||
$this->invoice_repo->restore($invoice);
|
||||
|
56
app/Http/Controllers/OpenAPI/TaskSchedulerSchema.php
Normal file
56
app/Http/Controllers/OpenAPI/TaskSchedulerSchema.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="TaskSchedulerSchema",
|
||||
* type="object",
|
||||
*
|
||||
*
|
||||
* @OA\Property(property="paused",type="boolean",example="false",description="The scheduler paused state"),
|
||||
* @OA\Property(property="repeat_every",type="string",example="DAY",description="Accepted values (DAY,WEEK,MONTH,3MONTHS,YEAR)"),
|
||||
* @OA\Property(property="start_from",type="integer",example="1652898504",description="Timestamp when we should start the scheduler, default is today"),
|
||||
* @OA\Property(property="job",type="string",example="create_credit_report",description="Job, we can find list of available jobs in Scheduler model"),
|
||||
* @OA\Property(property="date_range", type="string", example="last7", description="The string representation of the date range of data to be returned"),
|
||||
* @OA\Property(property="date_key", type="string", example="created_at", description="The date column to search between."),
|
||||
* @OA\Property(property="start_date", type="string", example="2022-10-31", description="The start date to search between"),
|
||||
* @OA\Property(property="end_date", type="string", example="2022-10-31", description="The end date to search between"),
|
||||
* @OA\Property(
|
||||
* property="report_keys",
|
||||
* type="array",
|
||||
* @OA\Items(
|
||||
* type="string",
|
||||
* description="Array of Keys to export",
|
||||
* example="['name','date']",
|
||||
* ),
|
||||
* ),
|
||||
*
|
||||
* )
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="UpdateTaskSchedulerSchema",
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(property="paused",type="boolean",example="false",description="The scheduler paused state"),
|
||||
* @OA\Property(property="repeat_every",type="string",example="DAY",description="Accepted values (DAY,WEEK,MONTH,3MONTHS,YEAR)"),
|
||||
* @OA\Property(property="start_from",type="integer",example="1652898504",description="Timestamp when we should start the scheduler, default is today"),
|
||||
* @OA\Property(property="job",type="string",example="create_credit_report",description="Job, we can find list of available jobs in Scheduler model"),
|
||||
* @OA\Property(property="date_range", type="string", example="last7", description="The string representation of the date range of data to be returned"),
|
||||
* @OA\Property(property="date_key", type="string", example="created_at", description="The date column to search between."),
|
||||
* @OA\Property(property="start_date", type="string", example="2022-10-31", description="The start date to search between"),
|
||||
* @OA\Property(property="end_date", type="string", example="2022-10-31", description="The end date to search between"),
|
||||
* )
|
||||
*/
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="UpdateJobForASchedulerSchema",
|
||||
* type="object",
|
||||
* @OA\Property(property="job",type="string",example="create_client_report",description="Set action name, action names can be found in Scheduler Model"),
|
||||
*
|
||||
* )
|
||||
*/
|
||||
|
@ -41,6 +41,7 @@ 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 Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
@ -51,6 +52,8 @@ class PreviewController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
use MakesInvoiceHtml;
|
||||
use PageNumbering;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@ -157,7 +160,15 @@ class PreviewController extends BaseController
|
||||
}
|
||||
|
||||
if(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){
|
||||
return (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
return $pdf;
|
||||
|
||||
}
|
||||
|
||||
//else
|
||||
@ -285,7 +296,14 @@ class PreviewController extends BaseController
|
||||
}
|
||||
|
||||
if(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){
|
||||
return (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
|
||||
$file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), $company);
|
||||
@ -354,7 +372,14 @@ class PreviewController extends BaseController
|
||||
}
|
||||
|
||||
if(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){
|
||||
return (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
|
||||
$file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), auth()->user()->company());
|
||||
@ -443,7 +468,14 @@ class PreviewController extends BaseController
|
||||
}
|
||||
|
||||
if(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){
|
||||
return (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
|
||||
$file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), auth()->user()->company());
|
||||
|
646
app/Http/Controllers/PurchaseOrderController.php
Normal file
646
app/Http/Controllers/PurchaseOrderController.php
Normal file
@ -0,0 +1,646 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
|
||||
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\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\UpdatePurchaseOrderRequest;
|
||||
use App\Jobs\Invoice\ZipInvoices;
|
||||
use App\Jobs\PurchaseOrder\PurchaseOrderEmail;
|
||||
use App\Jobs\PurchaseOrder\ZipPurchaseOrders;
|
||||
use App\Models\Client;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Repositories\PurchaseOrderRepository;
|
||||
use App\Transformers\PurchaseOrderTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class PurchaseOrderController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
protected $entity_type = PurchaseOrder::class;
|
||||
protected $entity_transformer = PurchaseOrderTransformer::class;
|
||||
protected $purchase_order_repository;
|
||||
|
||||
public function __construct(PurchaseOrderRepository $purchase_order_repository)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->purchase_order_repository = $purchase_order_repository;
|
||||
}
|
||||
/**
|
||||
* Show the list of Purchase Orders.
|
||||
*
|
||||
* @param \App\Filters\PurchaseOrderFilters $filters The filters
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/purchase_orders",
|
||||
* operationId="getPurchaseOrders",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Gets a list of purchase orders",
|
||||
* description="Lists purchase orders, search and filters allow fine grained lists to be generated.
|
||||
*
|
||||
* Query parameters can be added to performed more fine grained filtering of the purchase orders, these are handled by the PurchaseOrderFilters class which defines the methods available",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @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="A list of purchase orders",
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function index(PurchaseOrderFilters $filters)
|
||||
{
|
||||
$purchase_orders = PurchaseOrder::filter($filters);
|
||||
|
||||
return $this->listResponse($purchase_orders);
|
||||
}
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param CreatePurchaseOrderRequest $request The request
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/purchase_orders/create",
|
||||
* operationId="getPurchaseOrderCreate",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Gets a new blank purchase order object",
|
||||
* description="Returns a blank object with default values",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @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="A blank purchase order object",
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function create(CreatePurchaseOrderRequest $request)
|
||||
{
|
||||
$purchase_order = PurchaseOrderFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($purchase_order);
|
||||
}
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param StorePurchaseOrderRequest $request The request
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/purchase_orders",
|
||||
* operationId="storePurchaseOrder",
|
||||
* tags={"purhcase_orders"},
|
||||
* summary="Adds a purchase order",
|
||||
* description="Adds an purchase order to the system",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @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="Returns the saved purchase order object",
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function store(StorePurchaseOrderRequest $request)
|
||||
{
|
||||
|
||||
$purchase_order = $this->purchase_order_repository->save($request->all(), PurchaseOrderFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
$purchase_order = $purchase_order->service()
|
||||
->fillDefaults()
|
||||
->triggeredActions($request)
|
||||
->save();
|
||||
|
||||
event(new PurchaseOrderWasCreated($purchase_order, $purchase_order->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
return $this->itemResponse($purchase_order);
|
||||
}
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ShowPurchaseOrderRequest $request The request
|
||||
* @param PurchaseOrder $purchase_order The purchase order
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/purchase_orders/{id}",
|
||||
* operationId="showPurchaseOrder",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Shows an purcase orders",
|
||||
* description="Displays an purchase order by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The Purchase order Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the purchase order object",
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function show(ShowPurchaseOrderRequest $request, PurchaseOrder $purchase_order)
|
||||
{
|
||||
return $this->itemResponse($purchase_order);
|
||||
}
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param EditPurchaseOrderRequest $request The request
|
||||
* @param PurchaseOrder $purchase_order The purchase order
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/purchase_orders/{id}/edit",
|
||||
* operationId="editPurchaseOrder",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Shows an purchase order for editting",
|
||||
* description="Displays an purchase order by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The purchase order Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the purchase order object",
|
||||
* @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/Invoice"),
|
||||
* ),
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function edit(EditPurchaseOrderRequest $request, PurchaseOrder $purchase_order)
|
||||
{
|
||||
return $this->itemResponse($purchase_order);
|
||||
}
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param UpdatePurchaseOrderRequest $request The request
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @OA\Put(
|
||||
* path="/api/v1/purchase_order/{id}",
|
||||
* operationId="updatePurchaseOrder",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Updates an purchase order",
|
||||
* description="Handles the updating of an purchase order by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The purchase order Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the purchase order object",
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function update(UpdatePurchaseOrderRequest $request, PurchaseOrder $purchase_order)
|
||||
{
|
||||
if ($request->entityIsDeleted($purchase_order)) {
|
||||
return $request->disallowUpdate();
|
||||
}
|
||||
|
||||
$purchase_order = $this->purchase_order_repository->save($request->all(), $purchase_order);
|
||||
|
||||
event(new PurchaseOrderWasUpdated($purchase_order, $purchase_order->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
return $this->itemResponse($purchase_order);
|
||||
}
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param DestroyPurchaseOrderRequest $request
|
||||
* @param PurchaseOrder $purchase_order
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @throws \Exception
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/purchase_orders/{id}",
|
||||
* operationId="deletePurchaseOrder",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Deletes a purchase order",
|
||||
* description="Handles the deletion of an purchase orders by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The purhcase order Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns a HTTP status",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function destroy(DestroyPurchaseOrderRequest $request, PurchaseOrder $purchase_order)
|
||||
{
|
||||
$this->purchase_order_repository->delete($purchase_order);
|
||||
|
||||
return $this->itemResponse($purchase_order->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view.
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/purchase_orders/bulk",
|
||||
* operationId="bulkPurchaseOrderss",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Performs bulk actions on an array of purchase_orders",
|
||||
* description="",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/index"),
|
||||
* @OA\RequestBody(
|
||||
* description="Purchase Order IDS",
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Items(
|
||||
* type="integer",
|
||||
* description="Array of hashed IDs to be bulk 'actioned",
|
||||
* example="[0,1,2,3]",
|
||||
* ),
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="The Bulk Action response",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function bulk()
|
||||
{
|
||||
|
||||
$action = request()->input('action');
|
||||
|
||||
$ids = request()->input('ids');
|
||||
|
||||
$purchase_orders = PurchaseOrder::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||
|
||||
if (! $purchase_orders) {
|
||||
return response()->json(['message' => 'No Purchase Orders Found']);
|
||||
}
|
||||
|
||||
/*
|
||||
* Download Purchase Order/s
|
||||
*/
|
||||
|
||||
if ($action == 'bulk_download' && $purchase_orders->count() >= 1) {
|
||||
$purchase_orders->each(function ($purchase_order) {
|
||||
if (auth()->user()->cannot('view', $purchase_order)) {
|
||||
nlog("access denied");
|
||||
return response()->json(['message' => ctrans('text.access_denied')]);
|
||||
}
|
||||
});
|
||||
|
||||
ZipPurchaseOrders::dispatch($purchase_orders, $purchase_orders->first()->company, auth()->user());
|
||||
|
||||
return response()->json(['message' => ctrans('texts.sent_message')], 200);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the other actions to the switch
|
||||
*/
|
||||
$purchase_orders->each(function ($purchase_order, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $purchase_order)) {
|
||||
$this->performAction($purchase_order, $action, true);
|
||||
}
|
||||
});
|
||||
|
||||
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||
|
||||
return $this->listResponse(PurchaseOrder::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/purchase_orders/{id}/{action}",
|
||||
* operationId="actionPurchaseOrder",
|
||||
* tags={"purchase_orders"},
|
||||
* summary="Performs a custom action on an purchase order",
|
||||
* description="Performs a custom action on an purchase order.
|
||||
*
|
||||
* The current range of actions are as follows
|
||||
* - mark_paid
|
||||
* - download
|
||||
* - archive
|
||||
* - delete
|
||||
* - email",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The Purchase Order Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="action",
|
||||
* in="path",
|
||||
* description="The action string to be performed",
|
||||
* example="clone_to_quote",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the invoice object",
|
||||
* @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/Invoice"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
* @param ActionPurchaseOrderRequest $request
|
||||
* @param PurchaseOrder $purchase_order
|
||||
* @param $action
|
||||
* @return \App\Http\Controllers\Response|\Illuminate\Http\JsonResponse|Response|mixed|\Symfony\Component\HttpFoundation\StreamedResponse
|
||||
*/
|
||||
public function action(ActionPurchaseOrderRequest $request, PurchaseOrder $purchase_order, $action)
|
||||
{
|
||||
return $this->performAction($purchase_order, $action);
|
||||
}
|
||||
|
||||
private function performAction(PurchaseOrder $purchase_order, $action, $bulk = false)
|
||||
{
|
||||
/*If we are using bulk actions, we don't want to return anything */
|
||||
switch ($action) {
|
||||
case 'mark_sent':
|
||||
$purchase_order->service()->markSent()->save();
|
||||
|
||||
if (! $bulk) {
|
||||
return $this->itemResponse($purchase_order);
|
||||
}
|
||||
break;
|
||||
case 'download':
|
||||
|
||||
$file = $purchase_order->service()->getPurchaseOrderPdf();
|
||||
|
||||
return response()->streamDownload(function () use($file) {
|
||||
echo Storage::get($file);
|
||||
}, basename($file), ['Content-Type' => 'application/pdf']);
|
||||
|
||||
break;
|
||||
case 'restore':
|
||||
$this->purchase_order_repository->restore($purchase_order);
|
||||
|
||||
if (! $bulk) {
|
||||
return $this->listResponse($purchase_order);
|
||||
}
|
||||
break;
|
||||
case 'archive':
|
||||
$this->purchase_order_repository->archive($purchase_order);
|
||||
|
||||
if (! $bulk) {
|
||||
return $this->listResponse($purchase_order);
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
|
||||
$this->purchase_order_repository->delete($purchase_order);
|
||||
|
||||
if (! $bulk) {
|
||||
return $this->listResponse($purchase_order);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'email':
|
||||
//check query parameter for email_type and set the template else use calculateTemplate
|
||||
PurchaseOrderEmail::dispatch($purchase_order, $purchase_order->company);
|
||||
|
||||
|
||||
if (! $bulk) {
|
||||
return response()->json(['message' => 'email sent'], 200);
|
||||
}
|
||||
|
||||
default:
|
||||
return response()->json(['message' => ctrans('texts.action_unavailable', ['action' => $action])], 400);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -204,9 +204,9 @@ class RecurringInvoiceController extends BaseController
|
||||
{
|
||||
$recurring_invoice = $this->recurring_invoice_repo->save($request->all(), RecurringInvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
$offset = $recurring_invoice->client->timezone_offset();
|
||||
$recurring_invoice->next_send_date = Carbon::parse($recurring_invoice->next_send_date)->startOfDay()->addSeconds($offset);
|
||||
$recurring_invoice->saveQuietly();
|
||||
// $offset = $recurring_invoice->client->timezone_offset();
|
||||
// $recurring_invoice->next_send_date = Carbon::parse($recurring_invoice->next_send_date)->startOfDay()->addSeconds($offset);
|
||||
// $recurring_invoice->saveQuietly();
|
||||
|
||||
$recurring_invoice->service()
|
||||
->triggeredActions($request)
|
||||
|
@ -31,11 +31,11 @@ class CreditReportController extends BaseController
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/reports/clients",
|
||||
* operationId="getClientReport",
|
||||
* path="/api/v1/reports/credit",
|
||||
* operationId="getCreditReport",
|
||||
* tags={"reports"},
|
||||
* summary="Client reports",
|
||||
* description="Export client reports",
|
||||
* summary="Credit reports",
|
||||
* description="Export credit reports",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\RequestBody(
|
||||
|
@ -31,11 +31,11 @@ class QuoteItemReportController extends BaseController
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/reports/invoice_items",
|
||||
* path="/api/v1/reports/quote_items",
|
||||
* operationId="getQuoteItemReport",
|
||||
* tags={"reports"},
|
||||
* summary="Invoice item reports",
|
||||
* description="Export invoice item reports",
|
||||
* summary="Quote item reports",
|
||||
* description="Export Quote item reports",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\RequestBody(
|
||||
|
@ -16,6 +16,7 @@ use App\Models\Client;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\AppSetup;
|
||||
use App\Utils\Traits\ClientGroupSettingsSaver;
|
||||
use Beganovich\Snappdf\Snappdf;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@ -134,6 +135,15 @@ class SelfUpdateController extends BaseController
|
||||
|
||||
nlog("Extracting zip");
|
||||
|
||||
// try{
|
||||
// $s = new Snappdf;
|
||||
// $s->getChromiumPath();
|
||||
// chmod($this->generatePlatformExecutable($s->getChromiumPath()), 0755);
|
||||
// }
|
||||
// catch(\Exception $e){
|
||||
// nlog("I could not set the file permissions for chrome");
|
||||
// }
|
||||
|
||||
$zipFile = new \PhpZip\ZipFile();
|
||||
|
||||
$zipFile->openFile($file);
|
||||
@ -142,6 +152,14 @@ class SelfUpdateController extends BaseController
|
||||
|
||||
$zipFile->close();
|
||||
|
||||
// $zip = new \ZipArchive;
|
||||
|
||||
// $res = $zip->open($file);
|
||||
// if ($res === TRUE) {
|
||||
// $zip->extractTo(base_path());
|
||||
// $zip->close();
|
||||
// }
|
||||
|
||||
nlog("Finished extracting files");
|
||||
|
||||
unlink($file);
|
||||
|
@ -49,7 +49,7 @@ class SetupController extends Controller
|
||||
{
|
||||
$check = SystemHealth::check(false);
|
||||
|
||||
if ($check['system_health'] == true && $check['simple_db_check'] && Schema::hasTable('accounts') && $account = Account::all()->first()) {
|
||||
if ($check['system_health'] == true && $check['simple_db_check'] && Schema::hasTable('accounts') && $account = Account::first()) {
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
@ -211,29 +211,31 @@ class SetupController extends Controller
|
||||
public function checkPdf(Request $request)
|
||||
{
|
||||
try {
|
||||
if (config('ninja.pdf_generator') == 'phantom') {
|
||||
return $this->testPhantom();
|
||||
}
|
||||
|
||||
$pdf = new Snappdf();
|
||||
// if (config('ninja.pdf_generator') == 'phantom') {
|
||||
// return $this->testPhantom();
|
||||
// }
|
||||
|
||||
if (config('ninja.snappdf_chromium_path')) {
|
||||
$pdf->setChromiumPath(config('ninja.snappdf_chromium_path'));
|
||||
}
|
||||
// $pdf = new Snappdf();
|
||||
|
||||
if (config('ninja.snappdf_chromium_arguments')) {
|
||||
$pdf->clearChromiumArguments();
|
||||
$pdf->addChromiumArguments(config('ninja.snappdf_chromium_arguments'));
|
||||
}
|
||||
// if (config('ninja.snappdf_chromium_path')) {
|
||||
// $pdf->setChromiumPath(config('ninja.snappdf_chromium_path'));
|
||||
// }
|
||||
|
||||
$pdf = $pdf
|
||||
->setHtml('GENERATING PDFs WORKS! Thank you for using Invoice Ninja!')
|
||||
->generate();
|
||||
// if (config('ninja.snappdf_chromium_arguments')) {
|
||||
// $pdf->clearChromiumArguments();
|
||||
// $pdf->addChromiumArguments(config('ninja.snappdf_chromium_arguments'));
|
||||
// }
|
||||
|
||||
Storage::disk(config('filesystems.default'))->put('test.pdf', $pdf);
|
||||
Storage::disk('local')->put('test.pdf', $pdf);
|
||||
// $pdf = $pdf
|
||||
// ->setHtml('GENERATING PDFs WORKS! Thank you for using Invoice Ninja!')
|
||||
// ->generate();
|
||||
|
||||
return response(['url' => Storage::disk('local')->url('test.pdf')], 200);
|
||||
// Storage::disk(config('filesystems.default'))->put('test.pdf', $pdf);
|
||||
// Storage::disk('local')->put('test.pdf', $pdf);
|
||||
return response(['url' => ''], 200);
|
||||
|
||||
// return response(['url' => Storage::disk('local')->url('test.pdf')], 200);
|
||||
} catch (Exception $e) {
|
||||
nlog($e->getMessage());
|
||||
|
||||
|
243
app/Http/Controllers/TaskSchedulerController.php
Normal file
243
app/Http/Controllers/TaskSchedulerController.php
Normal file
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\TaskScheduler\CreateScheduledTaskRequest;
|
||||
use App\Http\Requests\TaskScheduler\UpdateScheduleRequest;
|
||||
use App\Jobs\Ninja\TaskScheduler;
|
||||
use App\Jobs\Report\ProfitAndLoss;
|
||||
use App\Models\Scheduler;
|
||||
use App\Repositories\TaskSchedulerRepository;
|
||||
use App\Transformers\TaskSchedulerTransformer;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class TaskSchedulerController extends BaseController
|
||||
{
|
||||
protected $entity_type = Scheduler::class;
|
||||
protected $entity_transformer = TaskSchedulerTransformer::class;
|
||||
protected TaskSchedulerRepository $scheduler_repository;
|
||||
|
||||
public function __construct(TaskSchedulerRepository $scheduler_repository)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->scheduler_repository = $scheduler_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\GET(
|
||||
* path="/api/v1/task_scheduler/",
|
||||
* operationId="getTaskSchedulers",
|
||||
* tags={"task_scheduler"},
|
||||
* summary="Task Scheduler Index",
|
||||
* description="Get all schedulers with associated jobs",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="success",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
|
||||
public function index()
|
||||
{
|
||||
|
||||
$schedulers = Scheduler::where('company_id', auth()->user()->company()->id);
|
||||
|
||||
return $this->listResponse($schedulers);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/task_scheduler/",
|
||||
* operationId="createTaskScheduler",
|
||||
* tags={"task_scheduler"},
|
||||
* summary="Create task scheduler with job ",
|
||||
* description="Create task scheduler with a job (action(job) request should be sent via request also. Example: We want client report to be job which will be run
|
||||
* multiple times, we should send the same parameters in the request as we would send if we wanted to get report, see example",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(ref="#/components/schemas/TaskSchedulerSchema")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="success",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
|
||||
public function store(CreateScheduledTaskRequest $request)
|
||||
{
|
||||
$scheduler = new Scheduler();
|
||||
$scheduler->service()->store($scheduler, $request);
|
||||
return $this->itemResponse($scheduler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\GET(
|
||||
* path="/api/v1/task_scheduler/{id}",
|
||||
* operationId="showTaskScheduler",
|
||||
* tags={"task_scheduler"},
|
||||
* summary="Show given scheduler",
|
||||
* description="Get scheduler with associated job",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The Scheduler Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="success",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
|
||||
public function show(Scheduler $scheduler)
|
||||
{
|
||||
return $this->itemResponse($scheduler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\PUT(
|
||||
* path="/api/v1/task_scheduler/{id}",
|
||||
* operationId="updateTaskScheduler",
|
||||
* tags={"task_scheduler"},
|
||||
* summary="Update task scheduler ",
|
||||
* description="Update task scheduler",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The Scheduler Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ), * @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(ref="#/components/schemas/UpdateTaskSchedulerSchema")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="success",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function update(Scheduler $scheduler, UpdateScheduleRequest $request)
|
||||
{
|
||||
$scheduler->service()->update($scheduler, $request);
|
||||
return $this->itemResponse($scheduler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @OA\DELETE(
|
||||
* path="/api/v1/task_scheduler/{id}",
|
||||
* operationId="destroyTaskScheduler",
|
||||
* tags={"task_scheduler"},
|
||||
* summary="Destroy Task Scheduler",
|
||||
* description="Destroy task scheduler and its associated job",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The Scheduler Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="success",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function destroy(Scheduler $scheduler)
|
||||
{
|
||||
$this->scheduler_repository->delete($scheduler);
|
||||
return $this->itemResponse($scheduler->fresh());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -362,6 +362,7 @@ class BillingPortalPurchase extends Component
|
||||
->service()
|
||||
->markSent()
|
||||
->fillDefaults()
|
||||
->adjustInventory()
|
||||
->save();
|
||||
|
||||
Cache::put($this->hash, [
|
||||
|
@ -60,6 +60,8 @@ class CheckClientExistence
|
||||
|
||||
session()->put('multiple_contacts', $multiple_contacts);
|
||||
|
||||
session()->put('is_silent', request()->has('silent'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class ShowInvoiceRequest extends Request
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->guard('contact')->user()->client_id === $this->invoice->client_id
|
||||
return auth()->guard('contact')->user()->client_id === (int)$this->invoice->client_id
|
||||
&& auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class ShowQuoteRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->guard('contact')->user()->client->id === $this->quote->client_id
|
||||
return auth()->guard('contact')->user()->client->id === (int)$this->quote->client_id
|
||||
&& auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES;
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,9 @@ class StorePaymentRequest extends Request
|
||||
}
|
||||
}
|
||||
|
||||
// if (array_key_exists('amount', $input))
|
||||
// $input['amount'] = 0;
|
||||
|
||||
if (isset($input['credits']) && is_array($input['credits']) === false) {
|
||||
$input['credits'] = null;
|
||||
}
|
||||
@ -94,8 +97,7 @@ class StorePaymentRequest extends Request
|
||||
public function rules()
|
||||
{
|
||||
$rules = [
|
||||
'amount' => 'sometimes|numeric',
|
||||
'amount' => [new PaymentAmountsBalanceRule(), new ValidCreditsPresentRule()],
|
||||
'amount' => ['numeric', 'bail', new PaymentAmountsBalanceRule(), new ValidCreditsPresentRule()],
|
||||
'client_id' => 'bail|required|exists:clients,id',
|
||||
'invoices.*.invoice_id' => 'bail|required|distinct|exists:invoices,id',
|
||||
'invoices.*.amount' => 'bail|required',
|
||||
|
@ -38,9 +38,12 @@ class StoreProductRequest extends Request
|
||||
$rules['documents'] = 'file|mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000';
|
||||
}
|
||||
|
||||
$rules['cost'] = 'numeric';
|
||||
$rules['price'] = 'numeric';
|
||||
$rules['quantity'] = 'numeric';
|
||||
$rules['cost'] = 'sometimes|numeric';
|
||||
$rules['price'] = 'sometimes|numeric';
|
||||
$rules['quantity'] = 'sometimes|numeric';
|
||||
$rules['in_stock_quantity'] = 'sometimes|numeric';
|
||||
$rules['stock_notification_threshold'] = 'sometimes|numeric';
|
||||
$rules['stock_notification'] = 'sometimes|bool';
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ class UpdateProductRequest extends Request
|
||||
$rules['cost'] = 'numeric';
|
||||
$rules['price'] = 'numeric';
|
||||
$rules['quantity'] = 'numeric';
|
||||
$rules['in_stock_quantity'] = 'sometimes|numeric';
|
||||
$rules['stock_notification_threshold'] = 'sometimes|numeric';
|
||||
$rules['stock_notification'] = 'sometimes|bool';
|
||||
|
||||
return $rules;
|
||||
}
|
||||
@ -60,6 +63,13 @@ class UpdateProductRequest extends Request
|
||||
$input['assigned_user_id'] = $this->decodePrimaryKey($input['assigned_user_id']);
|
||||
}
|
||||
|
||||
if(array_key_exists('in_stock_quantity', $input) && request()->has('update_in_stock_quantity') && request()->input('update_in_stock_quantity') == 'true'){
|
||||
|
||||
}
|
||||
elseif(array_key_exists('in_stock_quantity', $input)){
|
||||
unset($input['in_stock_quantity']);
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\PurchaseOrder;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
class ActionPurchaseOrderRequest extends Request
|
||||
{
|
||||
use MakesHash;
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private $error_msg;
|
||||
|
||||
// private $invoice;
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->purchase_order);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'action' => 'required'
|
||||
];
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if($this->action){
|
||||
$input['action'] = $this->action;
|
||||
} elseif (!array_key_exists('action', $input) ) {
|
||||
$this->error_msg = 'Action is a required field';
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'action' => $this->error_msg,
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\PurchaseOrder;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\PurchaseOrder;
|
||||
|
||||
class CreatePurchaseOrderRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('create', PurchaseOrder::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\PurchaseOrder;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class DestroyPurchaseOrderRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->purchase_order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
40
app/Http/Requests/PurchaseOrder/EditPurchaseOrderRequest.php
Normal file
40
app/Http/Requests/PurchaseOrder/EditPurchaseOrderRequest.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\PurchaseOrder;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class EditPurchaseOrderRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->user()->can('edit', $this->purchase_order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
40
app/Http/Requests/PurchaseOrder/ShowPurchaseOrderRequest.php
Normal file
40
app/Http/Requests/PurchaseOrder/ShowPurchaseOrderRequest.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\PurchaseOrder;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class ShowPurchaseOrderRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('view', $this->purchase_order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\PurchaseOrder;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StorePurchaseOrderRequest extends Request
|
||||
{
|
||||
use MakesHash;
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->user()->can('create', PurchaseOrder::class);
|
||||
}
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
$rules['vendor_id'] = 'bail|required|exists:vendors,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||
|
||||
$rules['number'] = ['nullable', Rule::unique('purchase_orders')->where('company_id', auth()->user()->company()->id)];
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\PurchaseOrder;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Utils\Traits\ChecksEntityStatus;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdatePurchaseOrderRequest extends Request
|
||||
{
|
||||
use ChecksEntityStatus;
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->purchase_order);
|
||||
}
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
if($this->number)
|
||||
$rules['number'] = Rule::unique('purchase_orders')->where('company_id', auth()->user()->company()->id)->ignore($this->purchase_order->id);
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$input['id'] = $this->purchase_order->id;
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
@ -55,6 +55,10 @@ class StoreRecurringExpenseRequest extends Request
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
if (array_key_exists('next_send_date', $input) && is_string($input['next_send_date'])) {
|
||||
$input['next_send_date_client'] = $input['next_send_date'];
|
||||
}
|
||||
|
||||
if (array_key_exists('category_id', $input) && is_string($input['category_id'])) {
|
||||
$input['category_id'] = $this->decodePrimaryKey($input['category_id']);
|
||||
}
|
||||
|
@ -66,6 +66,10 @@ class UpdateRecurringExpenseRequest extends Request
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
if (array_key_exists('next_send_date', $input) && is_string($input['next_send_date'])) {
|
||||
$input['next_send_date_client'] = $input['next_send_date'];
|
||||
}
|
||||
|
||||
if (array_key_exists('category_id', $input) && is_string($input['category_id'])) {
|
||||
$input['category_id'] = $this->decodePrimaryKey($input['category_id']);
|
||||
}
|
||||
|
@ -67,6 +67,10 @@ class StoreRecurringInvoiceRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if (array_key_exists('next_send_date', $input) && is_string($input['next_send_date'])) {
|
||||
$input['next_send_date_client'] = $input['next_send_date'];
|
||||
}
|
||||
|
||||
if (array_key_exists('design_id', $input) && is_string($input['design_id'])) {
|
||||
$input['design_id'] = $this->decodePrimaryKey($input['design_id']);
|
||||
}
|
||||
|
@ -61,6 +61,10 @@ class UpdateRecurringInvoiceRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if (array_key_exists('next_send_date', $input) && is_string($input['next_send_date'])) {
|
||||
$input['next_send_date_client'] = $input['next_send_date'];
|
||||
}
|
||||
|
||||
if (array_key_exists('design_id', $input) && is_string($input['design_id'])) {
|
||||
$input['design_id'] = $this->decodePrimaryKey($input['design_id']);
|
||||
}
|
||||
|
@ -31,9 +31,25 @@ class GenericReportRequest extends Request
|
||||
'start_date' => 'string|date',
|
||||
'end_date' => 'string|date',
|
||||
'date_key' => 'string',
|
||||
'date_range' => 'string',
|
||||
'date_range' => 'sometimes|string',
|
||||
'report_keys' => 'present|array',
|
||||
'send_email' => 'bool',
|
||||
'send_email' => 'required|bool',
|
||||
];
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(!array_key_exists('date_range', $input))
|
||||
$input['date_range'] = 'all';
|
||||
|
||||
if(!array_key_exists('report_keys', $input))
|
||||
$input['report_keys'] = [];
|
||||
|
||||
if(!array_key_exists('send_email', $input))
|
||||
$input['send_email'] = true;
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,18 @@ class ProfitLossRequest extends Request
|
||||
'is_income_billed' => 'required|bail|bool',
|
||||
'is_expense_billed' => 'required|bail|bool',
|
||||
'include_tax' => 'required|bail|bool',
|
||||
'date_range' => 'required|bail|string',
|
||||
'date_range' => 'sometimes|string',
|
||||
'send_email' => 'bool',
|
||||
];
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(!array_key_exists('date_range', $input))
|
||||
$input['date_range'] = 'all';
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -22,13 +22,6 @@ trait RuntimeFormRequest
|
||||
$instance = $validator->getValidatorInstance();
|
||||
|
||||
return $instance;
|
||||
// if ($instance->fails()) {
|
||||
// return $instance->errors();
|
||||
// }
|
||||
|
||||
// $validator->passedValidation();
|
||||
|
||||
// return $validator->all();
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Requests\TaskScheduler;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class CreateScheduledTaskRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'paused' => 'sometimes|bool',
|
||||
'repeat_every' => 'required|string|in:DAY,WEEK,MONTH,3MONTHS,YEAR',
|
||||
'start_from' => 'sometimes|string',
|
||||
'job' => 'required',
|
||||
];
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(!array_key_exists('start_from', $input))
|
||||
$input['start_from'] = now();
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
52
app/Http/Requests/TaskScheduler/UpdateScheduleRequest.php
Normal file
52
app/Http/Requests/TaskScheduler/UpdateScheduleRequest.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
|
||||
namespace App\Http\Requests\TaskScheduler;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateScheduleRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'paused' => 'sometimes|bool',
|
||||
'repeat_every' => 'sometimes|string|in:DAY,WEEK,BIWEEKLY,MONTH,3MONTHS,YEAR',
|
||||
'start_from' => 'sometimes',
|
||||
'scheduled_run'=>'sometimes'
|
||||
];
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if (isset($input['start_from'])) {
|
||||
$input['scheduled_run'] = Carbon::parse((int)$input['start_from']);
|
||||
$input['start_from'] = Carbon::parse((int)$input['start_from']);
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Requests\TaskScheduler;
|
||||
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class UpdateScheduledJobRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'action_name' => 'sometimes|string',
|
||||
];
|
||||
}
|
||||
}
|
@ -62,7 +62,7 @@ class ValidInvoicesRules implements Rule
|
||||
return false;
|
||||
}
|
||||
|
||||
$inv = Invoice::whereId($invoice['invoice_id'])->first();
|
||||
$inv = Invoice::withTrashed()->whereId($invoice['invoice_id'])->first();
|
||||
|
||||
if (! $inv) {
|
||||
|
||||
|
@ -562,7 +562,7 @@ class BaseImport
|
||||
}
|
||||
}
|
||||
|
||||
protected function finalizeImport()
|
||||
public function finalizeImport()
|
||||
{
|
||||
$data = [
|
||||
'errors' => $this->error_array,
|
||||
|
@ -61,9 +61,6 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->{$entity}();
|
||||
}
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
}
|
||||
|
||||
public function client()
|
||||
|
@ -41,7 +41,7 @@ class Freshbooks extends BaseImport
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
// $this->finalizeImport();
|
||||
}
|
||||
|
||||
public function client()
|
||||
|
@ -39,7 +39,7 @@ class Invoice2Go extends BaseImport
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
// $this->finalizeImport();
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ class Invoicely extends BaseImport
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
// $this->finalizeImport();
|
||||
}
|
||||
|
||||
public function client()
|
||||
|
@ -54,7 +54,7 @@ class Wave extends BaseImport implements ImportInterface
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
// $this->finalizeImport();
|
||||
}
|
||||
|
||||
public function client()
|
||||
|
@ -40,7 +40,7 @@ class Zoho extends BaseImport
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
// $this->finalizeImport();
|
||||
}
|
||||
|
||||
public function client()
|
||||
|
@ -71,6 +71,7 @@ class BaseTransformer
|
||||
|
||||
$client_id_search = $this->company
|
||||
->clients()
|
||||
->where('is_deleted', false)
|
||||
->where('id_number', $client_name);
|
||||
|
||||
if ($client_id_search->count() >= 1) {
|
||||
@ -79,6 +80,7 @@ class BaseTransformer
|
||||
|
||||
$client_name_search = $this->company
|
||||
->clients()
|
||||
->where('is_deleted', false)
|
||||
->where('name', $client_name);
|
||||
|
||||
if ($client_name_search->count() >= 1) {
|
||||
@ -86,10 +88,11 @@ class BaseTransformer
|
||||
}
|
||||
}
|
||||
if (!empty($client_email)) {
|
||||
$contacts = ClientContact::where(
|
||||
'company_id',
|
||||
$this->company->id
|
||||
)->where('email', $client_email);
|
||||
$contacts = ClientContact::whereHas('client', function($query){
|
||||
$query->where('is_deleted', false);
|
||||
})
|
||||
->where('company_id', $this->company->id)
|
||||
->where('email', $client_email);
|
||||
|
||||
if ($contacts->count() >= 1) {
|
||||
return $contacts->first()->client_id;
|
||||
@ -109,6 +112,7 @@ class BaseTransformer
|
||||
{
|
||||
return $this->company
|
||||
->clients()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -124,6 +128,7 @@ class BaseTransformer
|
||||
{
|
||||
return $this->company
|
||||
->vendors()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -139,6 +144,7 @@ class BaseTransformer
|
||||
{
|
||||
return $this->company
|
||||
->projects()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -154,6 +160,7 @@ class BaseTransformer
|
||||
{
|
||||
return $this->company
|
||||
->products()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $key)),
|
||||
])
|
||||
@ -186,6 +193,7 @@ class BaseTransformer
|
||||
{
|
||||
$client = $this->company
|
||||
->clients()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -203,6 +211,7 @@ class BaseTransformer
|
||||
{
|
||||
$product = $this->company
|
||||
->products()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $key)),
|
||||
])
|
||||
@ -273,6 +282,7 @@ class BaseTransformer
|
||||
|
||||
$tax_rate = $this->company
|
||||
->tax_rates()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -292,6 +302,7 @@ class BaseTransformer
|
||||
|
||||
$tax_rate = $this->company
|
||||
->tax_rates()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -341,6 +352,7 @@ class BaseTransformer
|
||||
{
|
||||
$invoice = $this->company
|
||||
->invoices()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $invoice_number)),
|
||||
])
|
||||
@ -358,6 +370,7 @@ class BaseTransformer
|
||||
{
|
||||
return $this->company
|
||||
->invoices()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $invoice_number)),
|
||||
])
|
||||
@ -371,6 +384,7 @@ class BaseTransformer
|
||||
{
|
||||
return $this->company
|
||||
->expenses()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $expense_number)),
|
||||
])
|
||||
@ -386,6 +400,7 @@ class BaseTransformer
|
||||
{
|
||||
return $this->company
|
||||
->quotes()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $quote_number)),
|
||||
])
|
||||
@ -401,6 +416,7 @@ class BaseTransformer
|
||||
{
|
||||
$invoice = $this->company
|
||||
->invoices()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $invoice_number)),
|
||||
])
|
||||
@ -418,6 +434,7 @@ class BaseTransformer
|
||||
{
|
||||
$vendor = $this->company
|
||||
->vendors()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -452,6 +469,7 @@ class BaseTransformer
|
||||
{
|
||||
$ec = $this->company
|
||||
->expense_categories()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
@ -486,6 +504,7 @@ class BaseTransformer
|
||||
{
|
||||
$project = $this->company
|
||||
->projects()
|
||||
->where('is_deleted', false)
|
||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $name)),
|
||||
])
|
||||
|
@ -94,6 +94,8 @@ class RecurringExpensesCron
|
||||
$expense->save();
|
||||
|
||||
$recurring_expense->next_send_date = $recurring_expense->nextSendDate();
|
||||
$recurring_expense->next_send_date_client = $recurring_expense->next_send_date;
|
||||
|
||||
$recurring_expense->remaining_cycles = $recurring_expense->remainingCycles();
|
||||
$recurring_expense->save();
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Entity Ninja (https://entityninja.com).
|
||||
* Invoice Ninja (https://entityninja.com).
|
||||
*
|
||||
* @link https://github.com/entityninja/entityninja source repository
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Entity Ninja LLC (https://entityninja.com)
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
@ -34,6 +34,8 @@ use App\Utils\PhantomJS\Phantom;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\MakesInvoiceHtml;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
use App\Utils\Traits\Pdf\PageNumbering;
|
||||
use App\Utils\Traits\Pdf\PDF;
|
||||
use App\Utils\Traits\Pdf\PdfMaker;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
@ -43,10 +45,11 @@ use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use setasign\Fpdi\PdfParser\StreamReader;
|
||||
|
||||
class CreateEntityPdf implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash;
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering;
|
||||
|
||||
public $entity;
|
||||
|
||||
@ -102,6 +105,7 @@ class CreateEntityPdf implements ShouldQueue
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
/* Forget the singleton*/
|
||||
@ -186,9 +190,23 @@ class CreateEntityPdf implements ShouldQueue
|
||||
|
||||
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) {
|
||||
@ -204,8 +222,8 @@ class CreateEntityPdf implements ShouldQueue
|
||||
try{
|
||||
|
||||
if(!Storage::disk($this->disk)->exists($path))
|
||||
|
||||
Storage::disk($this->disk)->makeDirectory($path, 0775);
|
||||
|
||||
Storage::disk($this->disk)->put($file_path, $pdf, 'public');
|
||||
|
||||
}
|
||||
@ -225,4 +243,5 @@ class CreateEntityPdf implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Entity Ninja (https://entityninja.com).
|
||||
*
|
||||
@ -34,6 +33,7 @@ use App\Utils\PhantomJS\Phantom;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\MakesInvoiceHtml;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
use App\Utils\Traits\Pdf\PageNumbering;
|
||||
use App\Utils\Traits\Pdf\PdfMaker;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
@ -46,7 +46,7 @@ use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class CreateRawPdf implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash;
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering;
|
||||
|
||||
public $entity;
|
||||
|
||||
@ -177,11 +177,22 @@ class CreateRawPdf implements ShouldQueue
|
||||
if($finfo->buffer($pdf) != 'application/pdf; charset=binary')
|
||||
{
|
||||
$pdf = $this->makePdf(null, null, $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) {
|
||||
|
@ -79,6 +79,8 @@ class CSVIngest implements ShouldQueue {
|
||||
|
||||
}
|
||||
|
||||
$engine->finalizeImport();
|
||||
|
||||
$this->checkContacts();
|
||||
}
|
||||
|
||||
|
125
app/Jobs/Inventory/AdjustProductInventory.php
Normal file
125
app/Jobs/Inventory/AdjustProductInventory.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Jobs\Inventory;
|
||||
|
||||
use App\Jobs\Mail\NinjaMailer;
|
||||
use App\Jobs\Mail\NinjaMailerJob;
|
||||
use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\Admin\InventoryNotificationObject;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
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 AdjustProductInventory implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public Company $company;
|
||||
|
||||
public Invoice $invoice;
|
||||
|
||||
public array $old_invoice;
|
||||
|
||||
public function __construct(Company $company, Invoice $invoice, ?array $old_invoice = [])
|
||||
{
|
||||
$this->company = $company;
|
||||
$this->invoice = $invoice;
|
||||
$this->old_invoice = $old_invoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
if(count($this->old_invoice) > 0)
|
||||
$this->existingInventoryAdjustment();
|
||||
|
||||
return $this->newInventoryAdjustment();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function middleware()
|
||||
{
|
||||
return [new WithoutOverlapping($this->company->company_key)];
|
||||
}
|
||||
|
||||
private function newInventoryAdjustment()
|
||||
{
|
||||
|
||||
$line_items = $this->invoice->line_items;
|
||||
|
||||
foreach($line_items as $item)
|
||||
{
|
||||
|
||||
$p = Product::where('product_key', $item->product_key)->where('company_id', $this->company->id)->where('in_stock_quantity', '>', 0)->first();
|
||||
|
||||
if(!$p)
|
||||
continue;
|
||||
|
||||
$p->in_stock_quantity -= $item->quantity;
|
||||
$p->saveQuietly();
|
||||
|
||||
if($p->stock_notification_threshold && $p->in_stock_quantity <= $p->stock_notification_threshold)
|
||||
$this->notifyStockLevels($p, 'product');
|
||||
elseif($this->company->stock_notification_threshold && $p->in_stock_quantity <= $this->company->stock_notification_threshold)
|
||||
$this->notifyStocklevels($p, 'company');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function existingInventoryAdjustment()
|
||||
{
|
||||
|
||||
foreach($this->old_invoice as $item)
|
||||
{
|
||||
$p = Product::where('product_key', $item->product_key)->where('company_id', $this->company->id)->first();
|
||||
|
||||
if(!$p)
|
||||
continue;
|
||||
|
||||
$p->in_stock_quantity += $item->quantity;
|
||||
$p->saveQuietly();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function notifyStocklevels(Product $product, string $notification_level)
|
||||
{
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new NinjaMailer( (new InventoryNotificationObject($product, $notification_level))->build() );
|
||||
$nmo->company = $this->company;
|
||||
$nmo->settings = $this->company->settings;
|
||||
$nmo->to_user = $this->company->owner();
|
||||
|
||||
NinjaMailerJob::dispatch($nmo);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -47,7 +47,7 @@ class ClientLedgerBalanceUpdate implements ShouldQueue
|
||||
*/
|
||||
public function handle() :void
|
||||
{
|
||||
nlog("Updating company ledger for client ". $this->client->id);
|
||||
// nlog("Updating company ledger for client ". $this->client->id);
|
||||
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
@ -71,14 +71,14 @@ class ClientLedgerBalanceUpdate implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
nlog("Updating Balance NOW");
|
||||
// nlog("Updating Balance NOW");
|
||||
|
||||
$company_ledger->balance = $last_record->balance + $company_ledger->adjustment;
|
||||
$company_ledger->save();
|
||||
|
||||
});
|
||||
|
||||
nlog("Updating company ledger for client ". $this->client->id);
|
||||
// nlog("Updating company ledger for client ". $this->client->id);
|
||||
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,8 @@ class SystemMaintenance implements ShouldQueue
|
||||
|
||||
nlog("Starting System Maintenance");
|
||||
|
||||
// if(Ninja::isHosted())
|
||||
// return;
|
||||
if(Ninja::isHosted())
|
||||
return;
|
||||
|
||||
$delete_pdf_days = config('ninja.maintenance.delete_pdfs');
|
||||
|
||||
|
124
app/Jobs/Ninja/TaskScheduler.php
Normal file
124
app/Jobs/Ninja/TaskScheduler.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Jobs\Ninja;
|
||||
|
||||
|
||||
use App\Jobs\Report\SendToAdmin;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Scheduler;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class TaskScheduler implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
foreach (MultiDB::$dbs as $db)
|
||||
{
|
||||
|
||||
MultiDB::setDB($db);
|
||||
|
||||
Scheduler::with('company')
|
||||
->where('paused', false)
|
||||
->where('is_deleted', false)
|
||||
->where('scheduled_run', '<', now())
|
||||
->cursor()
|
||||
->each(function ($scheduler){
|
||||
$this->doJob($scheduler);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function doJob(Scheduler $scheduler)
|
||||
{
|
||||
nlog("Doing job {$scheduler->action_name}");
|
||||
|
||||
$company = $scheduler->company;
|
||||
|
||||
$parameters = $scheduler->parameters;
|
||||
|
||||
|
||||
switch ($scheduler->action_name) {
|
||||
case Scheduler::CREATE_CLIENT_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'contacts.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_CLIENT_CONTACT_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'clients.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_CREDIT_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'credits.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_DOCUMENT_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'documents.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_EXPENSE_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'expense.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_INVOICE_ITEM_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'invoice_items.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_INVOICE_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'invoices.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_PAYMENT_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'payments.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_PRODUCT_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'products.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_PROFIT_AND_LOSS_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'profit_and_loss.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_QUOTE_ITEM_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'quote_items.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_QUOTE_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'quotes.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_RECURRING_INVOICE_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'recurring_invoices.csv');
|
||||
break;
|
||||
case Scheduler::CREATE_TASK_REPORT:
|
||||
SendToAdmin::dispatch($company, $parameters, $scheduler->action_class, 'tasks.csv');
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
$scheduler->scheduled_run = $scheduler->nextScheduledDate();
|
||||
$scheduler->save();
|
||||
}
|
||||
|
||||
}
|
102
app/Jobs/PurchaseOrder/PurchaseOrderEmail.php
Normal file
102
app/Jobs/PurchaseOrder/PurchaseOrderEmail.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Jobs\PurchaseOrder;
|
||||
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasEmailed;
|
||||
use App\Jobs\Mail\NinjaMailerJob;
|
||||
use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\Engine\PurchaseOrderEmailEngine;
|
||||
use App\Mail\VendorTemplateEmail;
|
||||
use App\Models\Company;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Utils\Ninja;
|
||||
use Exception;
|
||||
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 PurchaseOrderEmail implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public PurchaseOrder $purchase_order;
|
||||
|
||||
public Company $company;
|
||||
|
||||
public $template_data;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(PurchaseOrder $purchase_order, Company $company, $template_data = null)
|
||||
{
|
||||
$this->purchase_order = $purchase_order;
|
||||
$this->company = $company;
|
||||
$this->template_data = $template_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
$this->purchase_order->last_sent_date = now();
|
||||
|
||||
$this->purchase_order->invitations->load('contact.vendor.country', 'purchase_order.vendor.country', 'purchase_order.company')->each(function ($invitation) {
|
||||
|
||||
/* Don't fire emails if the company is disabled */
|
||||
if ($this->company->is_disabled)
|
||||
return true;
|
||||
|
||||
/* Set DB */
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
App::setLocale($invitation->contact->preferredLocale());
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
/* Mark entity sent */
|
||||
$invitation->purchase_order->service()->markSent()->save();
|
||||
|
||||
$email_builder = (new PurchaseOrderEmailEngine($invitation, 'purchase_order', $this->template_data))->build();
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new VendorTemplateEmail($email_builder, $invitation->contact, $invitation);
|
||||
$nmo->company = $this->company;
|
||||
$nmo->settings = $this->company->settings;
|
||||
$nmo->to_user = $invitation->contact;
|
||||
$nmo->entity_string = 'purchase_order';
|
||||
$nmo->invitation = $invitation;
|
||||
$nmo->reminder_template = 'purchase_order';
|
||||
$nmo->entity = $invitation->purchase_order;
|
||||
|
||||
NinjaMailerJob::dispatchNow($nmo);
|
||||
|
||||
|
||||
});
|
||||
|
||||
if ($this->purchase_order->invitations->count() >= 1) {
|
||||
event(new PurchaseOrderWasEmailed($this->purchase_order->invitations->first(), $this->purchase_order->invitations->first()->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
126
app/Jobs/PurchaseOrder/ZipPurchaseOrders.php
Normal file
126
app/Jobs/PurchaseOrder/ZipPurchaseOrders.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Jobs\PurchaseOrder;
|
||||
|
||||
use App\Jobs\Entity\CreateEntityPdf;
|
||||
use App\Jobs\Mail\NinjaMailerJob;
|
||||
use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Jobs\Util\UnlinkFile;
|
||||
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\DownloadInvoices;
|
||||
use App\Mail\DownloadPurchaseOrders;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use App\Utils\TempFile;
|
||||
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\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipArchive;
|
||||
|
||||
class ZipPurchaseOrders implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $purchase_orders;
|
||||
|
||||
private $company;
|
||||
|
||||
private $user;
|
||||
|
||||
public $settings;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
/**
|
||||
* @param $purchase_orders
|
||||
* @param Company $company
|
||||
* @param $email
|
||||
* @deprecated confirm to be deleted
|
||||
* Create a new job instance.
|
||||
*
|
||||
*/
|
||||
public function __construct($purchase_orders, Company $company, User $user)
|
||||
{
|
||||
$this->purchase_orders = $purchase_orders;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->user = $user;
|
||||
|
||||
$this->settings = $company->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
* @throws \ZipStream\Exception\FileNotFoundException
|
||||
* @throws \ZipStream\Exception\FileNotReadableException
|
||||
* @throws \ZipStream\Exception\OverflowException
|
||||
*/
|
||||
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
# create new zip object
|
||||
$zipFile = new \PhpZip\ZipFile();
|
||||
$file_name = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip';
|
||||
$invitation = $this->purchase_orders->first()->invitations->first();
|
||||
$path = $this->purchase_orders->first()->vendor->purchase_order_filepath($invitation);
|
||||
|
||||
$this->purchase_orders->each(function ($purchase_order){
|
||||
|
||||
CreatePurchaseOrderPdf::dispatchNow($purchase_order->invitations()->first());
|
||||
|
||||
});
|
||||
|
||||
try{
|
||||
|
||||
foreach ($this->purchase_orders as $purchase_order) {
|
||||
|
||||
$file = $purchase_order->service()->getPurchaseOrderPdf();
|
||||
$zip_file_name = basename($file);
|
||||
$zipFile->addFromString($zip_file_name, Storage::get($file));
|
||||
|
||||
}
|
||||
|
||||
Storage::put($path.$file_name, $zipFile->outputAsString());
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new DownloadPurchaseOrders(Storage::url($path.$file_name), $this->company);
|
||||
$nmo->to_user = $this->user;
|
||||
$nmo->settings = $this->settings;
|
||||
$nmo->company = $this->company;
|
||||
|
||||
NinjaMailerJob::dispatch($nmo);
|
||||
|
||||
UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1));
|
||||
|
||||
|
||||
}
|
||||
catch(\PhpZip\Exception\ZipException $e){
|
||||
nlog("could not make zip => ". $e->getMessage());
|
||||
}
|
||||
finally{
|
||||
$zipFile->close();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -87,6 +87,7 @@ class SendRecurring implements ShouldQueue
|
||||
->applyNumber()
|
||||
//->createInvitations() //need to only link invitations to those in the recurring invoice
|
||||
->fillDefaults()
|
||||
->adjustInventory()
|
||||
->save();
|
||||
|
||||
}
|
||||
@ -105,6 +106,7 @@ class SendRecurring implements ShouldQueue
|
||||
nlog("updating recurring invoice dates");
|
||||
/* Set next date here to prevent a recurring loop forming */
|
||||
$this->recurring_invoice->next_send_date = $this->recurring_invoice->nextSendDate();
|
||||
$this->recurring_invoice->next_send_date_client = $this->recurring_invoice->nextSendDateClient();
|
||||
$this->recurring_invoice->remaining_cycles = $this->recurring_invoice->remainingCycles();
|
||||
$this->recurring_invoice->last_sent_date = now();
|
||||
|
||||
|
@ -48,6 +48,7 @@ class SendToAdmin implements ShouldQueue
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
||||
MultiDB::setDb($this->company->db);
|
||||
$export = new $this->report_class($this->company, $this->request);
|
||||
$csv = $export->run();
|
||||
|
@ -89,6 +89,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\App;
|
||||
@ -187,6 +188,11 @@ class Import implements ShouldQueue
|
||||
$this->resources = $resources;
|
||||
}
|
||||
|
||||
public function middleware()
|
||||
{
|
||||
return [new WithoutOverlapping($this->company->account->key)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Jobs\Util;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Utils\Traits\Pdf\PageNumbering;
|
||||
use App\Utils\Traits\Pdf\PdfMaker;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
@ -21,7 +22,7 @@ use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PreviewPdf implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, PdfMaker;
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, PdfMaker, PageNumbering;
|
||||
|
||||
public $company;
|
||||
|
||||
@ -46,6 +47,13 @@ class PreviewPdf implements ShouldQueue
|
||||
|
||||
public function handle()
|
||||
{
|
||||
return $this->makePdf(null, null, $this->design_string);
|
||||
$pdf = $this->makePdf(null, null, $this->design_string);
|
||||
|
||||
$numbered_pdf = $this->pageNumbering($pdf, $this->company);
|
||||
|
||||
if($numbered_pdf)
|
||||
$pdf = $numbered_pdf;
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
}
|
||||
|
221
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
Normal file
221
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Jobs\Vendor;
|
||||
|
||||
use App\Exceptions\FilePermissionsFailure;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Account;
|
||||
use App\Models\Credit;
|
||||
use App\Models\CreditInvitation;
|
||||
use App\Models\Design;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Models\Quote;
|
||||
use App\Models\QuoteInvitation;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\RecurringInvoiceInvitation;
|
||||
use App\Services\PdfMaker\Design as PdfDesignModel;
|
||||
use App\Services\PdfMaker\Design as PdfMakerDesign;
|
||||
use App\Services\PdfMaker\PdfMaker as PdfMakerService;
|
||||
use App\Utils\HostedPDF\NinjaPdf;
|
||||
use App\Utils\HtmlEngine;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\PhantomJS\Phantom;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\MakesInvoiceHtml;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
use App\Utils\Traits\Pdf\PDF;
|
||||
use App\Utils\Traits\Pdf\PageNumbering;
|
||||
use App\Utils\Traits\Pdf\PdfMaker;
|
||||
use App\Utils\VendorHtmlEngine;
|
||||
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\Lang;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use setasign\Fpdi\PdfParser\StreamReader;
|
||||
|
||||
class CreatePurchaseOrderPdf implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering;
|
||||
|
||||
public $entity;
|
||||
|
||||
public $company;
|
||||
|
||||
public $contact;
|
||||
|
||||
private $disk;
|
||||
|
||||
public $invitation;
|
||||
|
||||
public $entity_string = '';
|
||||
|
||||
public $vendor;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param $invitation
|
||||
*/
|
||||
public function __construct($invitation, $disk = 'public')
|
||||
{
|
||||
$this->invitation = $invitation;
|
||||
$this->company = $invitation->company;
|
||||
|
||||
$this->entity = $invitation->purchase_order;
|
||||
$this->entity_string = 'purchase_order';
|
||||
|
||||
$this->contact = $invitation->contact;
|
||||
|
||||
$this->vendor = $invitation->contact->vendor;
|
||||
$this->vendor->load('company');
|
||||
|
||||
$this->disk = Ninja::isHosted() ? config('filesystems.default') : $disk;
|
||||
|
||||
}
|
||||
|
||||
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->company->locale());
|
||||
|
||||
/* Set customized translations _NOW_ */
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') {
|
||||
return (new Phantom)->generate($this->invitation);
|
||||
}
|
||||
|
||||
$entity_design_id = '';
|
||||
|
||||
$path = $this->vendor->purchase_order_filepath($this->invitation);
|
||||
$entity_design_id = 'purchase_order_design_id';
|
||||
|
||||
$file_path = $path.$this->entity->numberFormatter().'.pdf';
|
||||
|
||||
$entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey('Wpmbk5ezJn');
|
||||
|
||||
$design = Design::find($entity_design_id);
|
||||
|
||||
/* Catch all in case migration doesn't pass back a valid design */
|
||||
if(!$design)
|
||||
$design = Design::find(2);
|
||||
|
||||
$html = new VendorHtmlEngine($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' => null,
|
||||
'vendor' => $this->vendor,
|
||||
'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->company->getSetting('all_pages_header'),
|
||||
'all_pages_footer' => $this->entity->company->getSetting('all_pages_footer'),
|
||||
],
|
||||
'process_markdown' => $this->entity->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 ($pdf) {
|
||||
|
||||
try{
|
||||
|
||||
if(!Storage::disk($this->disk)->exists($path))
|
||||
Storage::disk($this->disk)->makeDirectory($path, 0775);
|
||||
|
||||
Storage::disk($this->disk)->put($file_path, $pdf, 'public');
|
||||
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
|
||||
throw new FilePermissionsFailure($e->getMessage());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $file_path;
|
||||
}
|
||||
|
||||
public function failed($e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -92,6 +92,9 @@ class PaymentNotification implements ShouldQueue
|
||||
|
||||
$analytics_id = $company->google_analytics_key;
|
||||
|
||||
if(!strlen($analytics_id) > 2)
|
||||
return;
|
||||
|
||||
$client = $payment->client;
|
||||
$amount = $payment->amount;
|
||||
|
||||
@ -124,6 +127,7 @@ class PaymentNotification implements ShouldQueue
|
||||
*/
|
||||
private function sendAnalytics($data)
|
||||
{
|
||||
|
||||
$data = utf8_encode($data);
|
||||
$curl = curl_init();
|
||||
|
||||
|
58
app/Listeners/PurchaseOrder/CreatePurchaseOrderActivity.php
Normal file
58
app/Listeners/PurchaseOrder/CreatePurchaseOrderActivity.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class CreatePurchaseOrderActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::CREATE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderArchivedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::ARCHIVE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
58
app/Listeners/PurchaseOrder/PurchaseOrderDeletedActivity.php
Normal file
58
app/Listeners/PurchaseOrder/PurchaseOrderDeletedActivity.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderDeletedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::DELETE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
59
app/Listeners/PurchaseOrder/PurchaseOrderEmailActivity.php
Normal file
59
app/Listeners/PurchaseOrder/PurchaseOrderEmailActivity.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://purchase_orderninja.com).
|
||||
*
|
||||
* @link https://github.com/purchase_orderninja/purchase_orderninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://purchase_orderninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderEmailActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->invitation->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->invitation->purchase_order->id;
|
||||
$fields->company_id = $event->invitation->purchase_order->company_id;
|
||||
$fields->vendor_contact_id = $event->invitation->purchase_order->vendor_contact_id;
|
||||
$fields->vendor_id = $event->invitation->purchase_order->vendor_id;
|
||||
$fields->activity_type_id = Activity::EMAIL_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->invitation->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderRestoredActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->purchase_order->user_id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->purchase_order_id = $event->purchase_order->id;
|
||||
$fields->vendor_id = $event->purchase_order->vendor_id;
|
||||
$fields->company_id = $event->purchase_order->company_id;
|
||||
$fields->activity_type_id = Activity::RESTORE_PURCHASE_ORDER;
|
||||
|
||||
$this->activity_repo->save($fields, $event->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
62
app/Listeners/PurchaseOrder/PurchaseOrderViewedActivity.php
Normal file
62
app/Listeners/PurchaseOrder/PurchaseOrderViewedActivity.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\PurchaseOrder;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class PurchaseOrderViewedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
|
||||
public $delay = 5;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activity_repo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->activity_repo = $activity_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass;
|
||||
|
||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->invitation->purchase_order->user_id;
|
||||
|
||||
$event->invitation->purchase_order->service()->markSent()->save();
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->company_id = $event->invitation->company_id;
|
||||
$fields->activity_type_id = Activity::VIEW_PURCHASE_ORDER;
|
||||
$fields->vendor_id = $event->invitation->purchase_order->vendor_id;
|
||||
$fields->vendor_contact_id = $event->invitation->vendor_contact_id;
|
||||
$fields->invitation_id = $event->invitation->id;
|
||||
$fields->purchase_order_id = $event->invitation->purchase_order_id;
|
||||
|
||||
$this->activity_repo->save($fields, $event->invitation->purchase_order, $event->event_vars);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user