Merge pull request #8477 from turbo124/v5-develop

Late fees for Locked invoices
This commit is contained in:
David Bomba 2023-04-27 11:20:52 +10:00 committed by GitHub
commit b93ee4468e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
161 changed files with 1593 additions and 1968 deletions

View File

@ -415,8 +415,8 @@ class CheckData extends Command
$invitation->company_id = $invoice->company_id;
$invitation->user_id = $invoice->user_id;
$invitation->invoice_id = $invoice->id;
$invitation->contact_id = ClientContact::whereClientId($invoice->client_id)->first()->id;
$invitation->invitation_key = Str::random(config('ninja.key_length'));
$invitation->client_contact_id = ClientContact::whereClientId($invoice->client_id)->first()->id;
$invitation->key = Str::random(config('ninja.key_length'));
$invitation->save();
}
}
@ -447,7 +447,7 @@ class CheckData extends Command
$contact_id = 'client_contact_id';
$contact_class = ClientContact::class;
$entity_key = \Illuminate\Support\Str::of(class_basename($entity))->snake()->append('_id')->value;
$entity_key = \Illuminate\Support\Str::of(class_basename($entity))->snake()->append('_id')->toString();
$entity_obj = get_class($entity).'Invitation';
if ($entity instanceof PurchaseOrder) {

View File

@ -42,11 +42,6 @@ class CreateAccount extends Command
*/
protected $signature = 'ninja:create-account {--email=} {--password=}';
/**
* Create a new command instance.
*
* @param InvoiceRepository $invoice_repo
*/
public function __construct()
{
parent::__construct();

View File

@ -60,7 +60,7 @@ class DesignUpdate extends Command
foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db);
$this->handleOnDb($db);
$this->handleOnDb();
}
MultiDB::setDB($current_db);

View File

@ -105,7 +105,7 @@ class HostedMigrations extends Command
Import::dispatch($import_file, $user->companies()->first(), $user);
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
\Mail::to($this->user)->send(new MigrationFailed($e, $e->getMessage()));
\Mail::to($user)->send(new MigrationFailed($e, $company));
if (app()->environment() !== 'production') {
info($e->getMessage());

View File

@ -44,7 +44,6 @@ class HostedUsers extends Command
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{

View File

@ -107,7 +107,7 @@ class ImportMigrations extends Command
Import::dispatch($import_file, $this->getUser()->companies()->first(), $this->getUser());
// StartMigration::dispatch($file->getRealPath(), $this->getUser(), $this->getUser()->companies()->first());
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
\Mail::to($this->user)->send(new MigrationFailed($e, $e->getMessage()));
\Mail::to($user)->send(new MigrationFailed($e, $company));
if (app()->environment() !== 'production') {
info($e->getMessage());

View File

@ -12,7 +12,6 @@
namespace App\Console\Commands;
use DirectoryIterator;
use Faker\Factory;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
@ -44,8 +43,6 @@ class OpenApiYaml extends Command
*/
public function __construct()
{
$this->faker = Factory::create();
parent::__construct();
}

View File

@ -47,7 +47,6 @@ class S3Cleanup extends Command
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{

View File

@ -57,7 +57,6 @@ class SendRemindersCron extends Command
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{

View File

@ -37,7 +37,7 @@ class AccountCreated extends GenericCounter
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class AccountDeleted extends GenericCounter
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class AccountPlatform extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class AccountSignup extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class BankAccountsCreated extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class DbQuery extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class EmailCount extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class EmailFailure extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class EmailInvoiceFailure extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class EmailSuccess extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class LivePreview extends GenericCounter
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class LoginFailure extends GenericCounter
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class LoginSuccess extends GenericCounter
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class EmailBounce extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class EmailSpam extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class MigrationFailure extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class QueueSize extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class SendRecurringFailure extends GenericMixedMetric
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class TrialFinished extends GenericCounter
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -37,7 +37,7 @@ class TrialStarted extends GenericCounter
*
* date("Y-m-d H:i:s")
*
* @var DateTime
* @var \DateTime
*/
public $datetime;

View File

@ -47,13 +47,14 @@ class AccountCreated
$this->event_vars = $event_vars;
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
// /**
// * Get the channels the event should broadcast on.
// *
// * @return Channel|array
// */
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
// return new PrivateChannel('channel-name');
}
}

View File

@ -49,13 +49,13 @@ class ClientWasArchived
$this->event_vars = $event_vars;
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
// /**
// * Get the channels the event should broadcast on.
// *
// * @return Channel|array
// */
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -44,6 +44,6 @@ class CompanyDocumentsDeleted
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -55,6 +55,6 @@ class ContactLoggedIn
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -26,29 +26,8 @@ class DesignWasArchived
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var Design
*/
public $design;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Design $design
* @param Company $company
* @param array $event_vars
*/
public function __construct(Design $design, Company $company, array $event_vars)
public function __construct(public Design $design, public Company $company, public array $event_vars)
{
$this->design = $design;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -58,6 +37,6 @@ class DesignWasArchived
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -11,9 +11,10 @@
namespace App\Events\Design;
use App\Models\Company;
use App\Models\Design;
use App\Models\Company;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
/**
* Class DesignWasCreated.
@ -22,29 +23,8 @@ class DesignWasCreated
{
use SerializesModels;
/**
* @var Design
*/
public $design;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Design $design
* @param Company $company
* @param array $event_vars
*/
public function __construct(Design $design, Company $company, array $event_vars)
public function __construct(public Design $design, public Company $company, public array $event_vars)
{
$this->design = $design;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -54,6 +34,6 @@ class DesignWasCreated
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -11,9 +11,10 @@
namespace App\Events\Design;
use App\Models\Company;
use App\Models\Design;
use App\Models\Company;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
/**
* Class DesignWasDeleted.
@ -22,29 +23,8 @@ class DesignWasDeleted
{
use SerializesModels;
/**
* @var Design
*/
public $design;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Design $design
* @param Company $company
* @param array $event_vars
*/
public function __construct(Design $design, Company $company, array $event_vars)
public function __construct(public Design $design, public Company $company, public array $event_vars)
{
$this->design = $design;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -54,6 +34,6 @@ class DesignWasDeleted
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -11,9 +11,10 @@
namespace App\Events\Design;
use App\Models\Company;
use App\Models\Design;
use App\Models\Company;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
/**
* Class DesignWasRestored.
@ -22,33 +23,8 @@ class DesignWasRestored
{
use SerializesModels;
/**
* @var Design
*/
public $design;
public $company;
public $event_vars;
public $fromDeleted;
/**
* Create a new event instance.
*
* @param Design $design
* @param Company $company
* @param array $event_vars
*/
public function __construct(Design $design, $fromDeleted, Company $company, array $event_vars)
public function __construct(public Design $design, public bool $fromDeleted, public Company $company, public array $event_vars)
{
$this->design = $design;
$this->fromDeleted = $fromDeleted;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -58,6 +34,6 @@ class DesignWasRestored
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -11,9 +11,10 @@
namespace App\Events\Design;
use App\Models\Company;
use App\Models\Design;
use App\Models\Company;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
/**
* Class DesignWasUpdated.
@ -22,29 +23,8 @@ class DesignWasUpdated
{
use SerializesModels;
/**
* @var Design
*/
public $design;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Design $design
* @param Company $company
* @param array $event_vars
*/
public function __construct(Design $design, Company $company, array $event_vars)
public function __construct(public Design $design, public Company $company, public array $event_vars)
{
$this->design = $design;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -54,6 +34,6 @@ class DesignWasUpdated
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -56,6 +56,6 @@ class DocumentWasArchived
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -22,29 +22,7 @@ class InvoiceReminderWasEmailed
{
use SerializesModels;
/**
* @var Invoice
*/
public $invitation;
public $reminder;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param InvoiceInvitation $invitation
* @param Company $company
* @param array $event_vars
*/
public function __construct(InvoiceInvitation $invitation, Company $company, array $event_vars, string $reminder)
public function __construct(public InvoiceInvitation $invitation, public Company $company, public array $event_vars, public int $reminder)
{
$this->invitation = $invitation;
$this->company = $company;
$this->event_vars = $event_vars;
$this->reminder = $reminder;
}
}

View File

@ -56,17 +56,17 @@ class InvoiceWasCreated implements ShouldBroadcast
*/
public function broadcastOn()
{
return ['simple-channel'];
return [];
}
/**
* Get the data to broadcast.
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
return ['id' => 'value'];
}
// /**
// * Get the data to broadcast.
// *
// * @return array<string, mixed>
// */
// public function broadcastWith(): array
// {
// return ['id' => 'value'];
// }
}

View File

@ -21,34 +21,7 @@ class InvoiceWasEmailedAndFailed
{
use SerializesModels;
public $invitation;
public $message;
public $company;
public $event_vars;
public $template;
/**
* Create a new event instance.
*
* @param $invitation
* @param Company $company
* @param string $errors
* @param array $event_vars
*/
public function __construct($invitation, Company $company, string $message, string $template, array $event_vars)
public function __construct(public mixed $invitation, public Company $company, public string $message, public string $template, public array $event_vars)
{
$this->invitation = $invitation;
$this->company = $company;
$this->message = $message;
$this->event_vars = $event_vars;
$this->template = $template;
}
}

View File

@ -22,14 +22,6 @@ class InvoiceWasViewed
{
use SerializesModels;
/**
* @var Invoice
*/
public $invitation;
public $company;
public $event_vars;
/**
* Create a new event instance.
@ -38,10 +30,7 @@ class InvoiceWasViewed
* @param Company $company
* @param array $event_vars
*/
public function __construct(InvoiceInvitation $invitation, Company $company, array $event_vars)
public function __construct(public InvoiceInvitation $invitation, Company $company, array $event_vars)
{
$this->invitation = $invitation;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -53,6 +53,6 @@ class MethodDeleted
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -19,26 +19,7 @@ class ProductWasArchived
{
use SerializesModels;
/**
* @var Product
*/
public $product;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Product $product
* @param Company $company
* @param array $event_vars
*/
public function __construct(Product $product, Company $company, array $event_vars)
public function __construct(public Product $product, public Company $company, public array $event_vars)
{
$this->product = $product;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -19,30 +19,7 @@ class ProductWasCreated
{
use SerializesModels;
/**
* @var Product
*/
public $product;
public $input;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Product $product
* @param $input
* @param Company $company
* @param array $event_vars
*/
public function __construct(Product $product, $input, Company $company, array $event_vars)
public function __construct(public Product $product, public mixed $input, public Company $company, public array $event_vars)
{
$this->product = $product;
$this->input = $input;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -19,26 +19,7 @@ class ProductWasDeleted
{
use SerializesModels;
/**
* @var Product
*/
public $product;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Product $product
* @param Company $company
* @param array $event_vars
*/
public function __construct(Product $product, Company $company, array $event_vars)
public function __construct(public Product $product, public Company $company, public array $event_vars)
{
$this->product = $product;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -22,29 +22,7 @@ class ProductWasRestored
{
use SerializesModels;
/**
* @var Product
*/
public $invoice;
public $company;
public $event_vars;
public $fromDeleted;
/**
* Create a new event instance.
*
* @param Product $invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(Product $product, $fromDeleted, Company $company, array $event_vars)
public function __construct(public Product $product, public bool $fromDeleted, public Company $company, public array $event_vars)
{
$this->product = $product;
$this->fromDeleted = $fromDeleted;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -11,6 +11,7 @@
namespace App\Events\Product;
use App\Models\Company;
use App\Models\Product;
use Illuminate\Queue\SerializesModels;
@ -18,26 +19,7 @@ class ProductWasUpdated
{
use SerializesModels;
/**
* @var Product
*/
public $product;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Product $product
* @param Company $company
* @param array $event_vars
*/
public function __construct(Product $product, Company $company, array $event_vars)
public function __construct(public Product $product, public Company $company, public array $event_vars)
{
$this->product = $product;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -12,7 +12,6 @@
namespace App\Events\PurchaseOrder;
use App\Models\Company;
use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderInvitation;
use Illuminate\Queue\SerializesModels;
@ -23,26 +22,7 @@ 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)
public function __construct(public PurchaseOrderInvitation $invitation, public Company $company, public array $event_vars)
{
$this->invitation = $invitation;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -22,29 +22,7 @@ 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)
public function __construct(public PurchaseOrder $purchase_order, public bool $fromDeleted, public Company $company, public array $event_vars)
{
$this->purchase_order = $purchase_order;
$this->fromDeleted = $fromDeleted;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -22,26 +22,7 @@ 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)
public function __construct(public PurchaseOrder $purchase_order, public Company $company, public array $event_vars)
{
$this->purchase_order = $purchase_order;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -23,26 +23,7 @@ class PurchaseOrderWasViewed
{
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)
public function __construct(public PurchaseOrderInvitation $invitation, public Company $company, public array $event_vars)
{
$this->invitation = $invitation;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -23,27 +23,7 @@ class QuoteWasEmailed
{
use SerializesModels;
public $invitation;
public $company;
public $event_vars;
public $template;
/**
* Create a new event instance.
*
* @param Quote $quote
* @param string $notes
* @param Company $company
* @param array $event_vars
*/
public function __construct(QuoteInvitation $invitation, Company $company, array $event_vars, string $template)
public function __construct(public QuoteInvitation $invitation, public Company $company, public array $event_vars, public string $template)
{
$this->invitation = $invitation;
$this->company = $company;
$this->event_vars = $event_vars;
$this->template = $template;
}
}

View File

@ -22,26 +22,7 @@ class RecurringInvoiceWasArchived
{
use SerializesModels;
/**
* @var Invoice
*/
public $recurring_invoice;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Invoice $recurring_invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(RecurringInvoice $recurring_invoice, Company $company, array $event_vars)
public function __construct(public RecurringInvoice $recurring_invoice, public Company $company, public array $event_vars)
{
$this->recurring_invoice = $recurring_invoice;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -22,26 +22,7 @@ class RecurringInvoiceWasDeleted
{
use SerializesModels;
/**
* @var RecurringInvoice
*/
public $recurring_invoice;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Invoice $invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(RecurringInvoice $recurring_invoice, Company $company, array $event_vars)
public function __construct(public RecurringInvoice $recurring_invoice, public Company $company, public array $event_vars)
{
$this->recurring_invoice = $recurring_invoice;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -22,30 +22,7 @@ class RecurringInvoiceWasRestored
{
use SerializesModels;
/**
* @var RecurringInvoice
*/
public $recurring_invoice;
public $fromDeleted;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Invoice $invoice
* @param $fromDeleted
* @param Company $company
* @param array $event_vars
*/
public function __construct(RecurringInvoice $recurring_invoice, $fromDeleted, Company $company, array $event_vars)
public function __construct(public RecurringInvoice $recurring_invoice, public bool $fromDeleted, public Company $company, public array $event_vars)
{
$this->recurring_invoice = $recurring_invoice;
$this->fromDeleted = $fromDeleted;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -24,26 +24,7 @@ class RecurringInvoiceWasUpdated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var Invoice
*/
public $recurring_invoice;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param RecurringInvoice $recurring_invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(RecurringInvoice $recurring_invoice, Company $company, array $event_vars)
public function __construct(public RecurringInvoice $recurring_invoice, public Company $company, public array $event_vars)
{
$this->recurring_invoice = $recurring_invoice;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -22,26 +22,7 @@ class RecurringQuoteWasDeleted
{
use SerializesModels;
/**
* @var RecurringQuote
*/
public $recurring_quote;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Invoice $invoice
* @param Company $company
* @param array $event_vars
*/
public function __construct(RecurringQuote $recurring_quote, Company $company, array $event_vars)
public function __construct(public RecurringQuote $recurring_quote, public Company $company, public array $event_vars)
{
$this->recurring_quote = $recurring_quote;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -22,30 +22,7 @@ class RecurringQuoteWasRestored
{
use SerializesModels;
/**
* @var RecurringQuote
*/
public $recurring_quote;
public $fromDeleted;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param Invoice $invoice
* @param $fromDeleted
* @param Company $company
* @param array $event_vars
*/
public function __construct(RecurringQuote $recurring_quote, $fromDeleted, Company $company, array $event_vars)
public function __construct(public RecurringQuote $recurring_quote, public bool $fromDeleted, public Company $company, public array $event_vars)
{
$this->recurring_quote = $recurring_quote;
$this->fromDeleted = $fromDeleted;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -24,26 +24,8 @@ class RecurringQuoteWasUpdated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var Invoice
*/
public $recurring_quote;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param RecurringQuote $recurring_quote
* @param Company $company
* @param array $event_vars
*/
public function __construct(RecurringQuote $recurring_quote, Company $company, array $event_vars)
public function __construct(public RecurringQuote $recurring_quote, public Company $company, public array $event_vars)
{
$this->recurring_quote = $recurring_quote;
$this->company = $company;
$this->event_vars = $event_vars;
}
}

View File

@ -47,6 +47,6 @@ class SubscriptionWasCreated
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -26,27 +26,8 @@ class UserLoggedIn
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var
*/
public $user;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param User $user
* @param Company $company
* @param array $event_vars
*/
public function __construct(User $user, Company $company, array $event_vars)
public function __construct(public User $user, public Company $company, public array $event_vars)
{
$this->user = $user;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -56,6 +37,6 @@ class UserLoggedIn
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -26,30 +26,8 @@ class UserWasArchived
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var
*/
public $user;
public $creating_user;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param User $user
* @param Company $company
* @param array $event_vars
*/
public function __construct(User $user, User $creating_user, Company $company, array $event_vars)
public function __construct(public User $user, public User $creating_user, public Company $company, public array $event_vars)
{
$this->user = $user;
$this->creating_user = $creating_user;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -59,6 +37,6 @@ class UserWasArchived
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -26,30 +26,8 @@ class UserWasCreated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var
*/
public $user;
public $creating_user;
public $company;
public $event_vars;
/**
* Create a new event instance.
*
* @param User $user
* @param Company $company
* @param array $event_vars
*/
public function __construct(User $user, User $creating_user, Company $company, array $event_vars)
public function __construct(public User $user, public User $creating_user, public Company $company, public array $event_vars)
{
$this->user = $user;
$this->creating_user = $creating_user;
$this->company = $company;
$this->event_vars = $event_vars;
}
/**
@ -59,6 +37,6 @@ class UserWasCreated
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -59,6 +59,6 @@ class UserWasDeleted
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -59,6 +59,6 @@ class UserWasRestored
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -59,6 +59,6 @@ class UserWasUpdated
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
return [];
}
}

View File

@ -11,28 +11,30 @@
namespace App\Exceptions;
use Throwable;
use PDOException;
use App\Utils\Ninja;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
use Illuminate\Database\Eloquent\RelationNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Sentry\State\Scope;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Queue\MaxAttemptsExceededException;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Schema;
use Illuminate\Validation\ValidationException;
use League\Flysystem\UnableToCreateDirectory;
use PDOException;
use Sentry\Laravel\Integration;
use Sentry\State\Scope;
use Illuminate\Support\Facades\Schema;
use GuzzleHttp\Exception\ConnectException;
use Illuminate\Auth\AuthenticationException;
use League\Flysystem\UnableToCreateDirectory;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Queue\MaxAttemptsExceededException;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Symfony\Component\Process\Exception\RuntimeException;
use Illuminate\Database\Eloquent\RelationNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
class Handler extends ExceptionHandler
{
@ -59,10 +61,9 @@ class Handler extends ExceptionHandler
ModelNotFoundException::class,
NotFoundHttpException::class,
UnableToCreateDirectory::class,
GuzzleHttp\Exception\ConnectException::class,
Symfony\Component\Process\Exception\RuntimeException::class,
InvalidArgumentException::class,
ConnectException::class,
RuntimeException::class,
InvalidArgumentException::class,
Aws\Exception\CredentialsException::class,
];

View File

@ -120,9 +120,9 @@ class ProductExport extends BaseExport
$entity['vendor'] = $product->vendor()->exists() ? $product->vendor->name : '';
}
if (array_key_exists('project_id', $this->input['report_keys'])) {
$entity['project'] = $product->project()->exists() ? $product->project->name : '';
}
// if (array_key_exists('project_id', $this->input['report_keys'])) {
// $entity['project'] = $product->project()->exists() ? $product->project->name : '';
// }
return $entity;
}

View File

@ -229,7 +229,7 @@ class ProductSalesExport extends BaseExport
/**
* calculateTax
*
* @param mixed $invoice
* @param Invoice $invoice
* @param float $amount
* @param float $tax_rate
* @return float
@ -250,7 +250,7 @@ class ProductSalesExport extends BaseExport
/**
* calculateDiscount
*
* @param mixed $invoice
* @param Invoice $invoice
* @param mixed $entity
* @return float
*/

View File

@ -57,5 +57,6 @@ class RecurringInvoiceFactory
$invoice->auto_bill = 'off';
return $invoice;
}
}

View File

@ -36,7 +36,7 @@ class BankIntegrationFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -55,7 +55,7 @@ class BankIntegrationFilters extends QueryFilters
* Filters the list based on the status
* archived, active, deleted.
*
* @param string filter
* @param string $filter
* @return Builder
*/
public function status(string $filter = ''): Builder

View File

@ -53,7 +53,7 @@ class ClientFilters extends QueryFilters
/**
* Filter between balances.
*
* @param string balance
* @param string $balance
* @return Builder
*/
public function between_balance(string $balance = ''): Builder
@ -108,7 +108,7 @@ class ClientFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -136,7 +136,7 @@ class ClientFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
@ -157,9 +157,9 @@ class ClientFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Query\Builder
* @return Builder
*/
public function entityFilter()
public function entityFilter(): Builder
{
return $this->builder->company();
}

View File

@ -21,7 +21,7 @@ class CompanyGatewayFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -39,7 +39,7 @@ class CompanyGatewayFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
@ -56,9 +56,9 @@ class CompanyGatewayFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Query\Builder
* @return Builder
*/
public function entityFilter()
public function entityFilter(): Builder
{
return $this->builder->company();
}

View File

@ -27,7 +27,7 @@ class CreditFilters extends QueryFilters
* - overdue
* - reversed
*
* @param string credit_status The credit status as seen by the client
* @param string $value The credit status as seen by the client
* @return Builder
*/
public function credit_status(string $value = ''): Builder
@ -66,7 +66,7 @@ class CreditFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -104,7 +104,7 @@ class CreditFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
@ -124,7 +124,7 @@ class CreditFilters extends QueryFilters
* 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
*
* @return Illuminate\Database\Query\Builder
* @return Builder
*/
public function entityFilter()
{

View File

@ -22,7 +22,7 @@ class DocumentFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -52,7 +52,7 @@ class DocumentFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
@ -79,9 +79,9 @@ class DocumentFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Query\Builder
* @return Builder
*/
public function entityFilter()
public function entityFilter(): Builder
{
return $this->builder->company();
}

View File

@ -21,7 +21,7 @@ class ExpenseCategoryFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -37,7 +37,7 @@ class ExpenseCategoryFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
@ -59,9 +59,9 @@ class ExpenseCategoryFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Query\Builder
* @return Builder
*/
public function entityFilter()
public function entityFilter(): Builder
{
return $this->builder->company();
}

View File

@ -21,7 +21,7 @@ class ExpenseFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -130,7 +130,7 @@ class ExpenseFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
@ -151,9 +151,9 @@ class ExpenseFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Query\Builder
* @return Builder
*/
public function entityFilter()
public function entityFilter(): Builder
{
return $this->builder->company();
}

View File

@ -156,7 +156,7 @@ class PaymentFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Eloquent\Builder
* @return Builder
*/
public function entityFilter(): Builder
{

View File

@ -21,8 +21,8 @@ class ProjectFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @return Illuminate\Eloquent\Query\Builder
* @param string $filter
* @return Builder
* @deprecated
*/
public function filter(string $filter = ''): Builder
@ -50,8 +50,8 @@ class ProjectFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @return Illuminate\Eloquent\Query\Builder
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
{
@ -69,7 +69,7 @@ class ProjectFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Eloquent\Query\Builder
* @return Builder
*/
public function entityFilter(): Builder
{

View File

@ -74,7 +74,7 @@ class PurchaseOrderFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -112,7 +112,7 @@ class PurchaseOrderFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder

View File

@ -151,7 +151,7 @@ class RecurringInvoiceFilters extends QueryFilters
/**
* next send date between.
*
* @param string range
* @param string $range
* @return Builder
*/
public function next_send_between(string $range = ''): Builder
@ -187,7 +187,7 @@ class RecurringInvoiceFilters extends QueryFilters
/**
* Filter by frequency id.
*
* @param integer frequency_id
* @param string $value
* @return Builder
*/
public function frequency_id(string $value = ''): Builder

View File

@ -21,8 +21,8 @@ class RecurringQuoteFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @return Illuminate\Database\Eloquent\Builder
* @param string $filter
* @return Builder
* @deprecated
*/
public function filter(string $filter = ''): Builder
@ -51,8 +51,8 @@ class RecurringQuoteFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @return Illuminate\Database\Eloquent\Builder
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder
{
@ -68,7 +68,7 @@ class RecurringQuoteFilters extends QueryFilters
/**
* Filters the query by the users company ID.
*
* @return Illuminate\Database\Eloquent\Builder
* @return Builder
*/
public function entityFilter(): Builder
{

View File

@ -21,7 +21,7 @@ class SchedulerFilters extends QueryFilters
/**
* Filter based on search text.
*
* @param string query filter
* @param string $filter
* @return Builder
* @deprecated
*/
@ -39,7 +39,7 @@ class SchedulerFilters extends QueryFilters
/**
* Sorts the list based on $sort.
*
* @param string sort formatted as column|asc
* @param string $sort formatted as column|asc
* @return Builder
*/
public function sort(string $sort = ''): Builder

View File

@ -11,13 +11,17 @@
namespace App\Helpers\Invoice;
use App\Models\Quote;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\PurchaseOrder;
use App\Models\RecurringQuote;
use App\DataMapper\InvoiceItem;
use App\DataMapper\BaseSettings;
use App\Models\RecurringInvoice;
use App\DataMapper\Tax\RuleInterface;
use App\Utils\Traits\NumberFormatter;
use App\DataMapper\Tax\ZipTax\Response;
class InvoiceItemSum
{
@ -59,7 +63,7 @@ class InvoiceItemSum
'AU', // Australia
];
protected $invoice;
protected RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice;
private $items;
@ -91,7 +95,7 @@ class InvoiceItemSum
private RuleInterface $rule;
public function __construct($invoice)
public function __construct( RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice)
{
$this->tax_collection = collect([]);
@ -108,9 +112,9 @@ class InvoiceItemSum
$this->line_items = [];
}
public function process()
public function process(): self
{
if (! $this->invoice->line_items || ! isset($this->invoice->line_items) || ! is_array($this->invoice->line_items) || count($this->invoice->line_items) == 0) {
if (!$this->invoice->line_items || !is_array($this->invoice->line_items)) {
$this->items = [];
return $this;
@ -121,7 +125,7 @@ class InvoiceItemSum
return $this;
}
private function calcLineItems()
private function calcLineItems(): self
{
foreach ($this->invoice->line_items as $this->item) {
$this->cleanLineItem()
@ -136,7 +140,7 @@ class InvoiceItemSum
private function shouldCalculateTax(): self
{
if (!$this->invoice->company?->calculate_taxes) {
if (!$this->invoice->company->calculate_taxes) {
$this->calc_tax = false;
return $this;
}
@ -159,7 +163,7 @@ class InvoiceItemSum
return $this;
}
private function push()
private function push(): self
{
$this->sub_total += $this->getLineTotal();

View File

@ -11,7 +11,12 @@
namespace App\Helpers\Invoice;
use App\Models\Quote;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\PurchaseOrder;
use App\Models\RecurringQuote;
use App\Models\RecurringInvoice;
use App\Utils\Traits\NumberFormatter;
class InvoiceItemSumInclusive
@ -20,11 +25,7 @@ class InvoiceItemSumInclusive
use Discounter;
use Taxer;
protected $invoice;
private $items;
private $line_total;
protected RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice;
private $currency;
@ -36,13 +37,9 @@ class InvoiceItemSumInclusive
private $sub_total;
private $total_discount;
private $tax_collection;
private $tax_amount;
public function __construct($invoice)
public function __construct(RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice)
{
$this->tax_collection = collect([]);
@ -60,7 +57,6 @@ class InvoiceItemSumInclusive
public function process()
{
if (! $this->invoice->line_items || ! is_array($this->invoice->line_items) || count($this->invoice->line_items) == 0) {
$this->items = [];
return $this;
}

View File

@ -11,9 +11,15 @@
namespace App\Helpers\Invoice;
use App\Models\Quote;
use App\Utils\Number;
use App\Models\Credit;
use App\Models\Invoice;
use App\Utils\Traits\NumberFormatter;
use App\Models\PurchaseOrder;
use App\Models\RecurringQuote;
use App\Models\RecurringInvoice;
use Illuminate\Support\Collection;
use App\Utils\Traits\NumberFormatter;
class InvoiceSum
{
@ -22,7 +28,7 @@ class InvoiceSum
use Discounter;
use NumberFormatter;
protected $invoice;
protected RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice;
public $tax_map;
@ -49,7 +55,7 @@ class InvoiceSum
/**
* Constructs the object with Invoice and Settings object.
*
* @param \App\Models\RecurringInvoice|\App\Models\Quote|\App\Models\Credit|\App\Models\PurchaseOrder|\App\Models\Invoice $invoice The entity
* @param RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice;
*/
public function __construct($invoice)
{
@ -78,7 +84,7 @@ class InvoiceSum
return $this;
}
private function calculateLineItems()
private function calculateLineItems(): self
{
$this->invoice_items = new InvoiceItemSum($this->invoice);
$this->invoice_items->process();
@ -90,7 +96,7 @@ class InvoiceSum
return $this;
}
private function calculateDiscount()
private function calculateDiscount(): self
{
$this->total_discount = $this->discount($this->invoice_items->getSubTotal());
@ -99,7 +105,7 @@ class InvoiceSum
return $this;
}
private function calculateCustomValues()
private function calculateCustomValues(): self
{
$this->total_custom_values += $this->valuer($this->invoice->custom_surcharge1);
@ -114,7 +120,7 @@ class InvoiceSum
return $this;
}
private function calculateInvoiceTaxes()
private function calculateInvoiceTaxes(): self
{
if (is_string($this->invoice->tax_name1) && strlen($this->invoice->tax_name1) > 1) {
$tax = $this->taxer($this->total, $this->invoice->tax_rate1);
@ -148,23 +154,24 @@ class InvoiceSum
*
* @return self The balance.
*/
private function calculateBalance()
private function calculateBalance(): self
{
$this->setCalculatedAttributes();
return $this;
}
private function calculatePartial()
private function calculatePartial(): self
{
if (! isset($this->invoice->id) && isset($this->invoice->partial)) {
$this->invoice->partial = max(0, min($this->formatValue($this->invoice->partial, 2), $this->invoice->balance));
$this->invoice->partial = max(0, min(Number::roundValue($this->invoice->partial, 2), $this->invoice->balance));
// $this->invoice->partial = max(0, min($this->formatValue($this->invoice->partial, 2), $this->invoice->balance));
}
return $this;
}
private function calculateTotals()
private function calculateTotals(): self
{
$this->total += $this->total_taxes;
@ -230,7 +237,7 @@ class InvoiceSum
* Build $this->invoice variables after
* calculations have been performed.
*/
private function setCalculatedAttributes()
private function setCalculatedAttributes(): self
{
/* If amount != balance then some money has been paid on the invoice, need to subtract this difference from the total to set the new balance */
@ -238,9 +245,9 @@ 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->precision) - $paid_to_date;
$this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision) - $paid_to_date;
} else {
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision);
$this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision);
}
}
/* Set new calculated total */
@ -268,7 +275,7 @@ class InvoiceSum
return $this->gross_sub_total;
}
public function setGrossSubTotal($value)
public function setGrossSubTotal($value): self
{
$this->gross_sub_total = $value;
@ -300,7 +307,7 @@ class InvoiceSum
return $this->total_custom_values;
}
public function setTaxMap()
public function setTaxMap(): self
{
if ($this->invoice->is_amount_discount == true) {
$this->invoice_items->calcTaxesWithAmountDiscount();
@ -369,18 +376,18 @@ class InvoiceSum
return $this->getTotalTaxes();
}
public function purgeTaxes()
public function purgeTaxes(): self
{
$this->tax_rate1 = 0;
$this->tax_name1 = '';
// $this->tax_rate1 = 0;
// $this->tax_name1 = '';
$this->tax_rate2 = 0;
$this->tax_name2 = '';
// $this->tax_rate2 = 0;
// $this->tax_name2 = '';
$this->tax_rate3 = 0;
$this->tax_name3 = '';
// $this->tax_rate3 = 0;
// $this->tax_name3 = '';
$this->discount = 0;
// $this->discount = 0;
$line_items = collect($this->invoice->line_items);

View File

@ -11,9 +11,15 @@
namespace App\Helpers\Invoice;
use App\Models\Quote;
use App\Models\Credit;
use App\Models\Invoice;
use App\Utils\Traits\NumberFormatter;
use App\Models\PurchaseOrder;
use App\Models\RecurringQuote;
use App\Models\RecurringInvoice;
use Illuminate\Support\Collection;
use App\Utils\Traits\NumberFormatter;
use App\Helpers\Invoice\InvoiceItemSumInclusive;
class InvoiceSumInclusive
{
@ -22,7 +28,7 @@ class InvoiceSumInclusive
use Discounter;
use NumberFormatter;
protected $invoice;
protected RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice;
public $tax_map;
@ -42,10 +48,11 @@ class InvoiceSumInclusive
private $precision;
public InvoiceItemSumInclusive $invoice_items;
/**
* Constructs the object with Invoice and Settings object.
*
* @param \App\Models\RecurringInvoice|\App\Models\Quote|\App\Models\Credit|\App\Models\PurchaseOrder|\App\Models\Invoice $invoice The entity
* @param RecurringInvoice | Invoice | Quote | Credit | PurchaseOrder | RecurringQuote $invoice;
*/
public function __construct($invoice)
{
@ -196,6 +203,9 @@ class InvoiceSumInclusive
return $this->invoice;
}
/**
* @return Invoice | RecurringInvoice | Quote | Credit | PurchaseOrder
*/
public function getInvoice()
{
//Build invoice values here and return Invoice
@ -205,6 +215,9 @@ class InvoiceSumInclusive
return $this->invoice;
}
/**
* @return Invoice | RecurringInvoice | Quote | Credit | PurchaseOrder
*/
public function getQuote()
{
//Build invoice values here and return Invoice
@ -214,6 +227,9 @@ class InvoiceSumInclusive
return $this->invoice;
}
/**
* @return Invoice | RecurringInvoice | Quote | Credit | PurchaseOrder
*/
public function getCredit()
{
//Build invoice values here and return Invoice
@ -223,6 +239,9 @@ class InvoiceSumInclusive
return $this->invoice;
}
/**
* @return Invoice | RecurringInvoice | Quote | Credit | PurchaseOrder
*/
public function getPurchaseOrder()
{
//Build invoice values here and return Invoice

View File

@ -15,7 +15,7 @@
*
* //Cache::forever($custom_company_translated_string, 'mogly');
*
* @param string translation string key
* @param string $string
* @param array $replace
* @param null $locale
* @return string

View File

@ -11,39 +11,40 @@
namespace App\Http\Controllers;
use App\Models\User;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Design;
use App\Utils\Statics;
use App\Models\Account;
use App\Models\TaxRate;
use App\Models\Webhook;
use App\Models\Scheduler;
use App\Models\TaskStatus;
use App\Models\PaymentTerm;
use Illuminate\Support\Str;
use League\Fractal\Manager;
use App\Models\GroupSetting;
use Illuminate\Http\Response;
use App\Models\CompanyGateway;
use App\Utils\Traits\AppSetup;
use App\Models\BankIntegration;
use App\Models\BankTransaction;
use App\Models\ExpenseCategory;
use League\Fractal\Resource\Item;
use App\Models\BankTransactionRule;
use Illuminate\Support\Facades\Auth;
use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\Design;
use App\Models\ExpenseCategory;
use App\Models\GroupSetting;
use App\Models\PaymentTerm;
use App\Models\Scheduler;
use App\Models\TaskStatus;
use App\Models\TaxRate;
use App\Models\User;
use App\Models\Webhook;
use App\Transformers\ArraySerializer;
use App\Transformers\EntityTransformer;
use League\Fractal\Resource\Collection;
use Illuminate\Database\Eloquent\Builder;
use League\Fractal\Serializer\JsonApiSerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use App\Utils\Ninja;
use App\Utils\Statics;
use App\Utils\Traits\AppSetup;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
/**
* Class BaseController.
* @method static Illuminate\Database\Eloquent\Builder exclude($columns)
*/
class BaseController extends Controller
{
@ -236,26 +237,26 @@ class BaseController extends Controller
* @param string $includes The includes for the object
* @return string The filtered array of includes
*/
private function filterIncludes(string $includes): string
{
$permissions_array = [
'payments' => 'view_payment',
'client' => 'view_client',
'clients' => 'view_client',
'vendor' => 'view_vendor',
'vendors' => 'view_vendors',
'expense' => 'view_expense',
'expenses' => 'view_expense',
];
// private function filterIncludes(string $includes): string
// {
// $permissions_array = [
// 'payments' => 'view_payment',
// 'client' => 'view_client',
// 'clients' => 'view_client',
// 'vendor' => 'view_vendor',
// 'vendors' => 'view_vendors',
// 'expense' => 'view_expense',
// 'expenses' => 'view_expense',
// ];
$collection = collect(explode(",", $includes));
// $collection = collect(explode(",", $includes));
$filtered_includes = $collection->filter(function ($include) use ($permissions_array) {
return auth()->user()->hasPermission($permissions_array[$include]);
});
// $filtered_includes = $collection->filter(function ($include) use ($permissions_array) {
// return auth()->user()->hasPermission($permissions_array[$include]);
// });
return $filtered_includes->implode(",");
}
// return $filtered_includes->implode(",");
// }
/**
* 404 for the client portal.
@ -294,10 +295,11 @@ class BaseController extends Controller
* Refresh API response with latest cahnges
*
* @param Builder $query
* @return Builder
* @return Response
*/
protected function refreshResponse($query)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$this->manager->parseIncludes($this->first_load);
@ -536,15 +538,19 @@ class BaseController extends Controller
$paginator = $query->paginate($limit);
$query = $paginator->getCollection();
/** @phpstan-ignore-next-line */
$query = $paginator->getCollection(); /** @phpstan-ignore-line */
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
} else {
$resource = new Collection($query, $transformer, $this->entity_type);
}
// else {
// $resource = new Collection($query, $transformer, $this->entity_type);
// }
return $this->response($this->manager->createData($resource)->toArray());
}
@ -566,10 +572,11 @@ class BaseController extends Controller
* Mini Load Query
*
* @param Builder $query
* @return void
*
*/
protected function miniLoadResponse($query)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$this->serializer = request()->input('serializer') ?: EntityTransformer::API_SERIALIZER_ARRAY;
@ -636,12 +643,15 @@ class BaseController extends Controller
$limit = $this->resolveQueryLimit();
$paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line */
$query = $paginator->getCollection();
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
} else {
$resource = new Collection($query, $transformer, $this->entity_type);
}
// else {
// $resource = new Collection($query, $transformer, $this->entity_type);
// }
return $this->response($this->manager->createData($resource)->toArray());
}
@ -654,15 +664,15 @@ class BaseController extends Controller
* @deprecated
* @return bool
*/
private function complexPermissionsUser(): bool
{
//if the user is attached to more than one company AND they are not an admin across all companies
if (auth()->user()->company_users()->count() > 1 && (auth()->user()->company_users()->where('is_admin', 1)->count() != auth()->user()->company_users()->count())) {
return true;
}
// private function complexPermissionsUser(): bool
// {
// //if the user is attached to more than one company AND they are not an admin across all companies
// if (auth()->user()->company_users()->count() > 1 && (auth()->user()->company_users()->where('is_admin', 1)->count() != auth()->user()->company_users()->count())) {
// return true;
// }
return false;
}
// return false;
// }
/**
* Passes back the miniloaded data response
@ -672,6 +682,7 @@ class BaseController extends Controller
*/
protected function timeConstrainedResponse($query)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($user->getCompany()->is_large) {
@ -899,13 +910,18 @@ class BaseController extends Controller
$limit = $this->resolveQueryLimit();
$paginator = $query->paginate($limit);
/** @phpstan-ignore-next-line */
$query = $paginator->getCollection();
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
} else {
$resource = new Collection($query, $transformer, $this->entity_type);
}
// else {
// $resource = new Collection($query, $transformer, $this->entity_type);
// }
return $this->response($this->manager->createData($resource)->toArray());
}
@ -914,7 +930,7 @@ class BaseController extends Controller
*
* @param Builder $query
*/
protected function listResponse($query)
protected function listResponse(Builder $query)
{
$this->buildManager();
@ -963,9 +979,10 @@ class BaseController extends Controller
$query = $paginator->getCollection();
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
} else {
$resource = new Collection($query, $transformer, $this->entity_type);
}
// else {
// $resource = new Collection($query, $transformer, $this->entity_type);
// }
return $this->response($this->manager->createData($resource)->toArray());
}
@ -974,7 +991,7 @@ class BaseController extends Controller
* Sorts the response by keys
*
* @param mixed $response
* @return void
* @return Response
*/
protected function response($response)
{
@ -994,7 +1011,11 @@ class BaseController extends Controller
}
if (request()->include_static) {
$response['static'] = Statics::company(auth()->user()->getCompany()->getLocale());
/** @var \App\Models\User $user */
$user = auth()->user();
$response['static'] = Statics::company($user->getCompany()->getLocale());
}
}
@ -1011,6 +1032,7 @@ class BaseController extends Controller
* Item Response
*
* @param mixed $item
* @return Response
*/
protected function itemResponse($item)
{
@ -1024,8 +1046,11 @@ class BaseController extends Controller
$resource = new Item($item, $transformer, $this->entity_type);
if (auth()->user() && request()->include_static) {
$data['static'] = Statics::company(auth()->user()->getCompany()->getLocale());
/** @var \App\Models\User $user */
$user = auth()->user();
if ($user && request()->include_static) {
$data['static'] = Statics::company($user->getCompany()->getLocale());
}
return $this->response($this->manager->createData($resource)->toArray());
@ -1057,7 +1082,11 @@ class BaseController extends Controller
* Thresholds for displaying large account on first load
*/
if (request()->has('first_load') && request()->input('first_load') == 'true') {
if (auth()->user()->getCompany()->is_large && request()->missing('updated_at')) {
/** @var \App\Models\User $user */
$user = auth()->user();
if ($user->getCompany()->is_large && request()->missing('updated_at')) {
$data = $this->mini_load;
} else {
$data = $this->first_load;
@ -1085,7 +1114,11 @@ class BaseController extends Controller
*/
public function flutterRoute()
{
if ((bool) $this->checkAppSetup() !== false && $account = Account::first()) {
/** @var \App\Models\Account $account */
//always redirect invoicing.co to invoicing.co
if (Ninja::isHosted() && !in_array(request()->getSchemeAndHttpHost(), ['https://staging.invoicing.co', 'https://invoicing.co', 'https://demo.invoicing.co', 'https://invoiceninja.net'])) {
return redirect()->secure('https://invoicing.co');
@ -1151,9 +1184,9 @@ class BaseController extends Controller
/**
* Sets the Flutter build to serve
*
* @return void
* @return string
*/
private function setBuild()
private function setBuild(): string
{
$build = '';

View File

@ -62,35 +62,9 @@ class PreviewController extends BaseController
/**
* Returns a template filled with entity variables.
*
* @return \Illuminate\Http\Response
*
* @OA\Post(
* path="/api/v1/preview",
* operationId="getPreview",
* tags={"preview"},
* summary="Returns a pdf preview",
* description="Returns a pdf preview.",
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Response(
* response=200,
* description="The pdf 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"),
* ),
* )
* @return mixed
*/
public function show()
{
if (request()->has('entity') &&
@ -154,10 +128,17 @@ class PreviewController extends BaseController
return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true));
}
/** @var \App\Models\User $user */
$user = auth()->user();
$company = $user->company();
if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') {
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
$numbered_pdf = $this->pageNumbering($pdf, $company);
if ($numbered_pdf) {
$pdf = $numbered_pdf;
@ -166,9 +147,8 @@ class PreviewController extends BaseController
return $pdf;
}
//else
$file_path = (new PreviewPdf($maker->getCompiledHTML(true), $company))->handle();
$file_path = (new PreviewPdf($maker->getCompiledHTML(true), auth()->user()->company()))->handle();
return response()->download($file_path, basename($file_path), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true);
}
@ -177,8 +157,13 @@ class PreviewController extends BaseController
public function design(DesignPreviewRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$pdf = (new PdfMock($request->all(), auth()->user()->company()))->build()->getPdf();
/** @var \App\Models\Company $company */
$company = $user->company();
$pdf = (new PdfMock($request->all(), $company))->build()->getPdf();
$response = Response::make($pdf, 200);
$response->header('Content-Type', 'application/pdf');
@ -192,7 +177,10 @@ class PreviewController extends BaseController
return response()->json(['message' => 'This server cannot handle this request.'], 400);
}
$company = auth()->user()->company();
/** @var \App\Models\User $user */
$user = auth()->user();
$company = $user->company();
MultiDB::setDb($company->db);
@ -218,6 +206,8 @@ class PreviewController extends BaseController
DB::connection(config('database.default'))->beginTransaction();
if ($request->has('entity_id')) {
/** @var \App\Models\BaseModel $class */
$entity_obj = $class::on(config('database.default'))
->with('client.company')
->where('id', $this->decodePrimaryKey($request->input('entity_id')))
@ -304,13 +294,16 @@ class PreviewController extends BaseController
return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true));
}
/** @var \App\Models\User $user */
$user = auth()->user();
/** @var \App\Models\Company $company */
$company = $user->company();
if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') {
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
$numbered_pdf = $this->pageNumbering($pdf, $company);
if ($numbered_pdf) {
$pdf = $numbered_pdf;
@ -335,11 +328,18 @@ class PreviewController extends BaseController
private function blankEntity()
{
/** @var \App\Models\User $user */
$user = auth()->user();
/** @var \App\Models\Company $company */
$company = $user->company();
App::forgetInstance('translator');
$t = app('translator');
$t->replace(Ninja::transformTranslations(auth()->user()->company()->settings));
$t->replace(Ninja::transformTranslations($company->settings));
$invitation = InvoiceInvitation::where('company_id', auth()->user()->company()->id)->orderBy('id', 'desc')->first();
$invitation = InvoiceInvitation::where('company_id', $company->id)->orderBy('id', 'desc')->first();
/* If we don't have a valid invitation in the system - create a mock using transactions */
if (! $invitation) {
@ -381,10 +381,16 @@ class PreviewController extends BaseController
return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true));
}
/** @var \App\Models\User $user */
$user = auth()->user();
/** @var \App\Models\Company $company */
$company = $user->company();
if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') {
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
$numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company());
$numbered_pdf = $this->pageNumbering($pdf, $company);
if ($numbered_pdf) {
$pdf = $numbered_pdf;
@ -393,7 +399,7 @@ class PreviewController extends BaseController
return $pdf;
}
$file_path = (new PreviewPdf($maker->getCompiledHTML(true), auth()->user()->company()))->handle();
$file_path = (new PreviewPdf($maker->getCompiledHTML(true), $company))->handle();
$response = Response::make($file_path, 200);
$response->header('Content-Type', 'application/pdf');
@ -403,40 +409,51 @@ class PreviewController extends BaseController
private function mockEntity()
{
DB::connection(auth()->user()->company()->db)->beginTransaction();
/** @var \App\Models\User $user */
$user = auth()->user();
/** @var \App\Models\Company $company */
$company = $user->company();
DB::connection($company->db)->beginTransaction();
/** @var \App\Models\Client $client */
$client = Client::factory()->create([
'user_id' => auth()->user()->id,
'company_id' => auth()->user()->company()->id,
'company_id' => $company->id,
]);
/** @var \App\Models\ClientContact $contact */
$contact = ClientContact::factory()->create([
'user_id' => auth()->user()->id,
'company_id' => auth()->user()->company()->id,
'company_id' => $company->id,
'client_id' => $client->id,
'is_primary' => 1,
'send_email' => true,
]);
/** @var \App\Models\Invoice $invoice */
$invoice = Invoice::factory()->create([
'user_id' => auth()->user()->id,
'company_id' => auth()->user()->company()->id,
'company_id' => $company->id,
'client_id' => $client->id,
'terms' => auth()->user()->company()->settings->invoice_terms,
'footer' => auth()->user()->company()->settings->invoice_footer,
'terms' => $company->settings->invoice_terms,
'footer' => $company->settings->invoice_footer,
'public_notes' => 'Sample Public Notes',
]);
$invitation = InvoiceInvitation::factory()->create([
'user_id' => auth()->user()->id,
'company_id' => auth()->user()->company()->id,
'company_id' => $company->id,
'invoice_id' => $invoice->id,
'client_contact_id' => $contact->id,
]);
$invoice->setRelation('invitations', $invitation);
$invoice->setRelation('client', $client);
$invoice->setRelation('company', auth()->user()->company());
$invoice->setRelation('company', $company);
$invoice->load('client.company');
$design_object = json_decode(json_encode(request()->input('design')));
@ -466,7 +483,7 @@ class PreviewController extends BaseController
->design($design)
->build();
DB::connection(auth()->user()->company()->db)->rollBack();
DB::connection($company->db)->rollBack();
if (request()->query('html') == 'true') {
return $maker->getCompiledHTML();
@ -479,7 +496,7 @@ class PreviewController extends BaseController
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, auth()->user()->company());
$numbered_pdf = $this->pageNumbering($pdf, $company);
if ($numbered_pdf) {
$pdf = $numbered_pdf;
@ -488,8 +505,7 @@ class PreviewController extends BaseController
return $pdf;
}
$file_path = (new PreviewPdf($maker->getCompiledHTML(true), auth()->user()->company()))->handle();
$file_path = (new PreviewPdf($maker->getCompiledHTML(true), $company))->handle();
$response = Response::make($file_path, 200);
$response->header('Content-Type', 'application/pdf');

View File

@ -99,9 +99,6 @@ class SelfUpdateController extends BaseController
nlog('Extracting zip');
//clean up old snappdf installations
//$this->cleanOldSnapChromeBinaries();
$zipFile = new \PhpZip\ZipFile();
$zipFile->openFile($file);
@ -144,29 +141,6 @@ class SelfUpdateController extends BaseController
return response()->json(['message' => 'Update completed'], 200);
}
private function cleanOldSnapChromeBinaries()
{
$current_revision = base_path('vendor/beganovich/snappdf/versions/revision.txt');
$current_revision_text = file_get_contents($current_revision);
$iterator = new \DirectoryIterator(base_path('vendor/beganovich/snappdf/versions'));
foreach ($iterator as $file) {
if ($file->isDir() && ! $file->isDot() && ($current_revision_text != $file->getFileName())) {
$directoryIterator = new \RecursiveDirectoryIterator(base_path('vendor/beganovich/snappdf/versions/'.$file->getFileName()), \RecursiveDirectoryIterator::SKIP_DOTS);
foreach (new \RecursiveIteratorIterator($directoryIterator) as $filex) {
unlink($filex->getPathName());
}
$this->deleteDirectory(base_path('vendor/beganovich/snappdf/versions/'.$file->getFileName()));
}
}
$iterator = null;
}
private function deleteDirectory($dir)
{
if (! file_exists($dir)) {

View File

@ -54,7 +54,6 @@ class LockedInvoiceRule implements Rule
switch ($lock_invoices) {
case 'off':
return true;
break;
case 'when_sent':
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
return false;
@ -62,17 +61,14 @@ class LockedInvoiceRule implements Rule
return true;
break;
case 'when_paid':
if ($this->invoice->status_id == Invoice::STATUS_PAID) {
return false;
}
return true;
break;
default:
return true;
break;
}
}
}

View File

@ -48,16 +48,19 @@ class AutoBill implements ShouldQueue
MultiDB::setDb($this->db);
}
$invoice = false;
try {
nlog("autobill {$this->invoice_id}");
$invoice = Invoice::withTrashed()->find($this->invoice_id);
$invoice->service()->autoBill();
} catch (\Exception $e) {
nlog("Failed to capture payment for {$this->invoice_id} ->".$e->getMessage());
if($this->send_email_on_failure)
if($this->send_email_on_failure && $invoice)
{
$invoice->invitations->each(function ($invitation) use ($invoice) {

View File

@ -61,7 +61,7 @@ class EmailEntity implements ShouldQueue
* EmailEntity constructor.
*
*
* @param Invitation $invitation
* @param mixed $invitation
* @param Company $company
* @param ?string $reminder_template
* @param array $template_data
@ -146,21 +146,26 @@ class EmailEntity implements ShouldQueue
} elseif ($this->invitation instanceof RecurringInvoiceInvitation) {
return 'recurring_invoice';
}
return '';
}
/* Switch statement to handle failure notifications */
private function entityEmailFailed($message)
{
switch ($this->entity_string) {
case 'invoice':
event(new InvoiceWasEmailedAndFailed($this->invitation, $this->company, $message, $this->reminder_template, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
break;
/**
* @deprecated
* @unused
*/
// private function entityEmailFailed($message)
// {
// switch ($this->entity_string) {
// case 'invoice':
// event(new InvoiceWasEmailedAndFailed($this->invitation, $this->company, $message, $this->reminder_template, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
// break;
default:
// code...
break;
}
}
// default:
// // code...
// break;
// }
// }
/* Builds the email builder object */
private function resolveEmailBuilder()

View File

@ -52,7 +52,7 @@ class NinjaMailerJob implements ShouldQueue
public $override;
/* @var Company $company*/
public $company;
public ?Company $company;
private $mailer;
@ -580,10 +580,10 @@ class NinjaMailerJob implements ShouldQueue
/**
* Attempts to refresh the Microsoft refreshToken
*
* @param App\Models\User
* @return string | boool
* @param \App\Models\User $user
* @return mixed
*/
private function refreshOfficeToken($user)
private function refreshOfficeToken(User $user)
{
$expiry = $user->oauth_user_token_expiry ?: now()->subDay();

View File

@ -12,6 +12,7 @@
namespace App\Jobs\Util;
use App\DataMapper\InvoiceItem;
use App\Factory\InvoiceFactory;
use App\Jobs\Entity\EmailEntity;
use App\Jobs\Ninja\TransactionLog;
use App\Libraries\MultiDB;
@ -109,8 +110,13 @@ class ReminderJob implements ShouldQueue
}
}
private function sendReminderForInvoice($invoice)
private function sendReminderForInvoice(Invoice $invoice)
{
App::forgetInstance('translator');
$t = app('translator');
$t->replace(Ninja::transformTranslations($invoice->client->getMergedSettings()));
App::setLocale($invoice->client->locale());
if ($invoice->isPayable()) {
//Attempts to prevent duplicates from sending
if ($invoice->reminder_last_sent && Carbon::parse($invoice->reminder_last_sent)->startOfDay()->eq(now()->startOfDay())) {
@ -121,7 +127,14 @@ class ReminderJob implements ShouldQueue
$reminder_template = $invoice->calculateTemplate('invoice');
nlog("reminder template = {$reminder_template}");
$invoice->service()->touchReminder($reminder_template)->save();
$invoice = $this->calcLateFee($invoice, $reminder_template);
$fees = $this->calcLateFee($invoice, $reminder_template);
if(in_array($invoice->client->getSetting('lock_invoices'), ['when_sent','when_paid'])) {
return $this->addFeeToNewInvoice($invoice, $reminder_template, $fees);
}
else
$invoice = $this->setLateFee($invoice, $fees[0], $fees[1]);
//20-04-2022 fixes for endless reminders - generic template naming was wrong
$enabled_reminder = 'enable_'.$reminder_template;
@ -148,14 +161,84 @@ class ReminderJob implements ShouldQueue
}
}
private function addFeeToNewInvoice(Invoice $over_due_invoice, string $reminder_template, array $fees): void
{
$amount = $fees[0];
$percent = $fees[1];
$temp_invoice_balance = $over_due_invoice->balance;
if ($amount <= 0 && $percent <= 0) {
return;
}
$fee = $amount;
if ($over_due_invoice->partial > 0) {
$fee += round($over_due_invoice->partial * $percent / 100, 2);
} else {
$fee += round($over_due_invoice->balance * $percent / 100, 2);
}
/** @var \App\Models\Invoice $invoice */
$invoice = InvoiceFactory::create($over_due_invoice->company_id, $over_due_invoice->user_id);
$invoice->client_id = $over_due_invoice->client_id;
$invoice->date = now()->format('Y-m-d');
$invoice->due_date = now()->format('Y-m-d');
$invoice_item = new InvoiceItem();
$invoice_item->type_id = '5';
$invoice_item->product_key = trans('texts.fee');
$invoice_item->notes = ctrans('texts.late_fee_added_locked_invoice', ['invoice' => $over_due_invoice->number, 'date' => $this->translateDate(now()->startOfDay(), $over_due_invoice->client->date_format(), $over_due_invoice->client->locale())]);
$invoice_item->quantity = 1;
$invoice_item->cost = $fee;
$invoice_items = [];
$invoice_items[] = $invoice_item;
$invoice->line_items = $invoice_items;
/**Refresh Invoice values*/
$invoice = $invoice->calc()->getInvoice();
$invoice->service()
->createInvitations()
->applyNumber()
->markSent()
->save();
$invoice->service()->touchPdf(true);
$enabled_reminder = 'enable_'.$reminder_template;
if ($reminder_template == 'endless_reminder') {
$enabled_reminder = 'enable_reminder_endless';
}
if (in_array($reminder_template, ['reminder1', 'reminder2', 'reminder3', 'reminder_endless', 'endless_reminder']) &&
$invoice->client->getSetting($enabled_reminder) &&
$invoice->client->getSetting('send_reminders') &&
(Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) {
$invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
if ($invitation->contact && !$invitation->contact->trashed() && $invitation->contact->email) {
EmailEntity::dispatch($invitation, $invitation->company, $reminder_template);
nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
$invoice->entityEmailEvent($invitation, $reminder_template);
}
});
}
$invoice->service()->setReminder()->save();
}
/**
* Calculates the late if - if any - and rebuilds the invoice
*
* @param Invoice $invoice
* @param string $template
* @return Invoice
* @return array
*/
private function calcLateFee($invoice, $template): Invoice
private function calcLateFee($invoice, $template): array
{
$late_fee_amount = 0;
$late_fee_percent = 0;
@ -183,7 +266,8 @@ class ReminderJob implements ShouldQueue
break;
}
return $this->setLateFee($invoice, $late_fee_amount, $late_fee_percent);
return [$late_fee_amount, $late_fee_percent];
// return $this->setLateFee($invoice, $late_fee_amount, $late_fee_percent);
}
/**
@ -197,10 +281,6 @@ class ReminderJob implements ShouldQueue
*/
private function setLateFee($invoice, $amount, $percent): Invoice
{
App::forgetInstance('translator');
$t = app('translator');
$t->replace(Ninja::transformTranslations($invoice->client->getMergedSettings()));
App::setLocale($invoice->client->locale());
$temp_invoice_balance = $invoice->balance;
@ -236,16 +316,6 @@ class ReminderJob implements ShouldQueue
$invoice->client->service()->updateBalance($invoice->balance - $temp_invoice_balance);
$invoice->ledger()->updateInvoiceBalance($invoice->balance - $temp_invoice_balance, "Late Fee Adjustment for invoice {$invoice->number}");
// $transaction = [
// 'invoice' => $invoice->transaction_event(),
// 'payment' => [],
// 'client' => $invoice->client->transaction_event(),
// 'credit' => [],
// 'metadata' => ['setLateFee'],
// ];
// TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $invoice->company->db);
$invoice->service()->touchPdf(true);
return $invoice;

View File

@ -16,7 +16,6 @@ use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Libraries\MultiDB;
use App\Mail\Admin\EntitySentObject;
use App\Notifications\Admin\EntitySentNotification;
use App\Utils\Traits\Notifications\UserNotifies;
use Illuminate\Contracts\Queue\ShouldQueue;

View File

@ -130,50 +130,12 @@ use Laracasts\Presenter\PresentableTrait;
* @method static \Illuminate\Database\Eloquent\Builder|Account whereUtmMedium($value)
* @method static \Illuminate\Database\Eloquent\Builder|Account whereUtmSource($value)
* @method static \Illuminate\Database\Eloquent\Builder|Account whereUtmTerm($value)
* @method static \Illuminate\Database\Eloquent\Builder|Account first()
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @mixin \Eloquent
*/
class Account extends BaseModel
@ -184,14 +146,12 @@ class Account extends BaseModel
private $free_plan_email_quota = 20;
private $paid_plan_email_quota = 500;
/**
* @var string
*/
protected $presenter = AccountPresenter::class;
/**
* @var array
*/
protected $fillable = [
'plan',
'plan_term',
@ -450,6 +410,8 @@ class Account extends BaseModel
}
$trial_active = false;
$trial_expires = false;
$trial_started = false;
//14 day trial
$duration = 60*60*24*14;
@ -464,10 +426,11 @@ class Account extends BaseModel
}
$plan_active = false;
$plan_expires = false;
if ($plan) {
if ($this->plan_expires == null) {
$plan_active = true;
$plan_expires = false;
} else {
$plan_expires = Carbon::parse($this->plan_expires);
if ($plan_expires->greaterThan(now())) {
@ -480,7 +443,6 @@ class Account extends BaseModel
return null;
}
// Should we show plan details or trial details?
if (($plan && ! $trial_plan) || ! $include_trial) {
$use_plan = true;
@ -662,10 +624,10 @@ class Account extends BaseModel
$plan_expires = Carbon::parse($this->plan_expires);
if (!$this->payment_id && $plan_expires->gt(now())) {
if ($plan_expires->gt(now())) {
$diff = $plan_expires->diffInDays();
if ($diff > 14);
if ($diff > 14)
return 0;
return $diff;

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