2020-02-03 11:33:07 +01:00
|
|
|
<?php
|
|
|
|
/**
|
2020-09-06 11:38:10 +02:00
|
|
|
* Invoice Ninja (https://invoiceninja.com).
|
2020-02-03 11:33:07 +01:00
|
|
|
*
|
|
|
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
|
|
*
|
2022-04-27 05:20:41 +02:00
|
|
|
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
2020-02-03 11:33:07 +01:00
|
|
|
*
|
2021-06-16 08:58:16 +02:00
|
|
|
* @license https://www.elastic.co/licensing/elastic-license
|
2020-02-03 11:33:07 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
namespace App\Services\Invoice;
|
|
|
|
|
2022-03-24 03:50:55 +01:00
|
|
|
use App\Events\Invoice\InvoiceWasArchived;
|
2020-10-26 20:10:04 +01:00
|
|
|
use App\Jobs\Entity\CreateEntityPdf;
|
2022-05-31 13:17:18 +02:00
|
|
|
use App\Jobs\Inventory\AdjustProductInventory;
|
2021-02-05 06:03:34 +01:00
|
|
|
use App\Jobs\Invoice\InvoiceWorkflowSettings;
|
2020-10-10 05:32:10 +02:00
|
|
|
use App\Jobs\Util\UnlinkFile;
|
2021-03-27 04:51:34 +01:00
|
|
|
use App\Libraries\Currency\Conversion\CurrencyApi;
|
2020-08-25 15:06:38 +02:00
|
|
|
use App\Models\CompanyGateway;
|
2020-11-01 08:53:43 +01:00
|
|
|
use App\Models\Expense;
|
2020-02-03 11:33:07 +01:00
|
|
|
use App\Models\Invoice;
|
|
|
|
use App\Models\Payment;
|
2020-11-01 08:53:43 +01:00
|
|
|
use App\Models\Task;
|
2021-08-08 00:40:04 +02:00
|
|
|
use App\Repositories\BaseRepository;
|
2020-02-03 11:33:07 +01:00
|
|
|
use App\Services\Client\ClientService;
|
2021-08-13 03:30:48 +02:00
|
|
|
use App\Services\Invoice\ApplyPaymentAmount;
|
2021-05-26 02:35:39 +02:00
|
|
|
use App\Services\Invoice\UpdateReminder;
|
2021-05-24 12:58:37 +02:00
|
|
|
use App\Utils\Ninja;
|
2020-11-01 08:53:43 +01:00
|
|
|
use App\Utils\Traits\MakesHash;
|
2020-02-03 11:33:07 +01:00
|
|
|
use Illuminate\Support\Carbon;
|
2021-03-10 02:28:12 +01:00
|
|
|
use Illuminate\Support\Facades\Storage;
|
2020-02-03 11:33:07 +01:00
|
|
|
|
|
|
|
class InvoiceService
|
|
|
|
{
|
2020-11-01 08:53:43 +01:00
|
|
|
use MakesHash;
|
|
|
|
|
2021-11-09 11:15:08 +01:00
|
|
|
public $invoice;
|
2020-02-03 11:33:07 +01:00
|
|
|
|
|
|
|
public function __construct($invoice)
|
|
|
|
{
|
|
|
|
$this->invoice = $invoice;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-02-14 04:32:22 +01:00
|
|
|
* Marks as invoice as paid
|
2020-09-06 11:38:10 +02:00
|
|
|
* and executes child sub functions.
|
2020-02-03 11:33:07 +01:00
|
|
|
* @return $this InvoiceService object
|
|
|
|
*/
|
|
|
|
public function markPaid()
|
|
|
|
{
|
2021-09-26 11:56:09 +02:00
|
|
|
$this->removeUnpaidGatewayFees();
|
|
|
|
|
2021-07-14 04:22:37 +02:00
|
|
|
$this->invoice = (new MarkPaid($this->invoice))->run();
|
2020-02-03 11:33:07 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2021-08-13 03:30:48 +02:00
|
|
|
public function applyPaymentAmount($amount)
|
|
|
|
{
|
|
|
|
$this->invoice = (new ApplyPaymentAmount($this->invoice, $amount))->run();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
/**
|
2020-09-06 11:38:10 +02:00
|
|
|
* Applies the invoice number.
|
2020-02-03 11:33:07 +01:00
|
|
|
* @return $this InvoiceService object
|
|
|
|
*/
|
|
|
|
public function applyNumber()
|
|
|
|
{
|
2020-04-04 12:32:42 +02:00
|
|
|
$this->invoice = (new ApplyNumber($this->invoice->client, $this->invoice))->run();
|
2020-02-03 11:33:07 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2021-03-29 04:14:55 +02:00
|
|
|
/**
|
|
|
|
* Sets the exchange rate on the invoice if the client currency
|
|
|
|
* is different to the company currency.
|
|
|
|
*/
|
2021-03-27 04:51:34 +01:00
|
|
|
public function setExchangeRate()
|
|
|
|
{
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($this->invoice->exchange_rate != 1) {
|
2022-02-08 10:36:07 +01:00
|
|
|
return $this;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2022-02-08 10:36:07 +01:00
|
|
|
|
2021-03-29 04:14:55 +02:00
|
|
|
$client_currency = $this->invoice->client->getSetting('currency_id');
|
|
|
|
$company_currency = $this->invoice->company->settings->currency_id;
|
|
|
|
|
|
|
|
if ($company_currency != $client_currency) {
|
|
|
|
$exchange_rate = new CurrencyApi();
|
|
|
|
|
|
|
|
$this->invoice->exchange_rate = $exchange_rate->exchangeRate($client_currency, $company_currency, now());
|
|
|
|
}
|
2020-09-08 12:34:14 +02:00
|
|
|
|
2021-03-27 04:51:34 +01:00
|
|
|
return $this;
|
|
|
|
}
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2020-09-08 12:34:14 +02:00
|
|
|
/**
|
|
|
|
* Applies the recurring invoice number.
|
|
|
|
* @return $this InvoiceService object
|
|
|
|
*/
|
|
|
|
public function applyRecurringNumber()
|
|
|
|
{
|
|
|
|
$this->invoice = (new ApplyRecurringNumber($this->invoice->client, $this->invoice))->run();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
/**
|
|
|
|
* Apply a payment amount to an invoice.
|
|
|
|
* @param Payment $payment The Payment
|
|
|
|
* @param float $payment_amount The Payment amount
|
|
|
|
* @return InvoiceService Parent class object
|
|
|
|
*/
|
|
|
|
public function applyPayment(Payment $payment, float $payment_amount)
|
|
|
|
{
|
2021-04-09 11:51:17 +02:00
|
|
|
$this->deletePdf();
|
|
|
|
|
2020-04-04 12:32:42 +02:00
|
|
|
$this->invoice = (new ApplyPayment($this->invoice, $payment, $payment_amount))->run();
|
2020-02-03 11:33:07 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-10-12 11:38:55 +02:00
|
|
|
public function addGatewayFee(CompanyGateway $company_gateway, $gateway_type_id, float $amount)
|
2020-08-25 15:06:38 +02:00
|
|
|
{
|
2020-10-12 11:38:55 +02:00
|
|
|
$this->invoice = (new AddGatewayFee($company_gateway, $gateway_type_id, $this->invoice, $amount))->run();
|
2020-08-25 15:06:38 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2020-09-06 11:38:10 +02:00
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
/**
|
2020-09-06 11:38:10 +02:00
|
|
|
* Update an invoice balance.
|
|
|
|
*
|
2020-02-03 11:33:07 +01:00
|
|
|
* @param float $balance_adjustment The amount to adjust the invoice by
|
|
|
|
* a negative amount will REDUCE the invoice balance, a positive amount will INCREASE
|
|
|
|
* the invoice balance
|
2020-09-06 11:38:10 +02:00
|
|
|
*
|
2020-02-03 11:33:07 +01:00
|
|
|
* @return InvoiceService Parent class object
|
|
|
|
*/
|
2021-10-25 02:49:11 +02:00
|
|
|
public function updateBalance($balance_adjustment, bool $is_draft = false)
|
2020-02-03 11:33:07 +01:00
|
|
|
{
|
2022-06-21 11:57:17 +02:00
|
|
|
if ((bool) $this->invoice->is_deleted !== false) {
|
|
|
|
nlog($this->invoice->number.' is deleted returning');
|
2021-11-19 07:13:57 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2022-03-26 12:21:35 +01:00
|
|
|
$this->invoice->balance += $balance_adjustment;
|
2022-06-21 11:57:17 +02:00
|
|
|
|
|
|
|
if (round($this->invoice->balance, 2) == 0 && ! $is_draft) {
|
2021-11-19 07:13:57 +01:00
|
|
|
$this->invoice->status_id = Invoice::STATUS_PAID;
|
|
|
|
}
|
2020-02-03 11:33:07 +01:00
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if ((int) $this->invoice->balance == 0) {
|
2020-11-25 15:19:52 +01:00
|
|
|
$this->invoice->next_send_date = null;
|
|
|
|
}
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2021-01-24 07:44:14 +01:00
|
|
|
public function updatePaidToDate($adjustment)
|
|
|
|
{
|
2022-03-26 12:21:35 +01:00
|
|
|
$this->invoice->paid_to_date += $adjustment;
|
2021-01-24 07:44:14 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-02-04 08:51:44 +01:00
|
|
|
public function createInvitations()
|
|
|
|
{
|
2020-04-04 12:32:42 +02:00
|
|
|
$this->invoice = (new CreateInvitations($this->invoice))->run();
|
2020-02-04 08:51:44 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
public function markSent()
|
2020-03-21 06:37:30 +01:00
|
|
|
{
|
2020-04-15 02:30:52 +02:00
|
|
|
$this->invoice = (new MarkSent($this->invoice->client, $this->invoice))->run();
|
2020-02-03 11:33:07 +01:00
|
|
|
|
2021-03-29 04:14:55 +02:00
|
|
|
$this->setExchangeRate();
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2020-04-15 02:30:52 +02:00
|
|
|
return $this;
|
2020-02-03 11:33:07 +01:00
|
|
|
}
|
|
|
|
|
2020-05-09 00:35:49 +02:00
|
|
|
public function getInvoicePdf($contact = null)
|
2020-02-12 01:41:17 +01:00
|
|
|
{
|
2020-04-16 10:41:25 +02:00
|
|
|
return (new GetInvoicePdf($this->invoice, $contact))->run();
|
2020-02-12 01:41:17 +01:00
|
|
|
}
|
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
public function getInvoiceDeliveryNote(Invoice $invoice, \App\Models\ClientContact $contact = null)
|
2020-11-04 02:27:07 +01:00
|
|
|
{
|
2020-11-09 14:30:50 +01:00
|
|
|
return (new GenerateDeliveryNote($invoice, $contact))->run();
|
2020-11-04 02:27:07 +01:00
|
|
|
}
|
|
|
|
|
2020-05-09 00:35:49 +02:00
|
|
|
public function sendEmail($contact = null)
|
2020-02-15 10:01:15 +01:00
|
|
|
{
|
2020-02-17 10:37:44 +01:00
|
|
|
$send_email = new SendEmail($this->invoice, null, $contact);
|
2020-02-12 01:41:17 +01:00
|
|
|
|
2020-02-17 10:37:44 +01:00
|
|
|
return $send_email->run();
|
2020-02-15 10:01:15 +01:00
|
|
|
}
|
2020-02-12 01:41:17 +01:00
|
|
|
|
2020-04-08 12:48:31 +02:00
|
|
|
public function handleReversal()
|
2020-04-04 12:32:42 +02:00
|
|
|
{
|
2020-04-08 12:48:31 +02:00
|
|
|
$this->invoice = (new HandleReversal($this->invoice))->run();
|
2020-04-04 12:32:42 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-04-08 15:31:22 +02:00
|
|
|
public function handleCancellation()
|
|
|
|
{
|
2021-08-29 13:17:27 +02:00
|
|
|
$this->removeUnpaidGatewayFees();
|
|
|
|
|
2020-04-08 15:31:22 +02:00
|
|
|
$this->invoice = (new HandleCancellation($this->invoice))->run();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-09-23 12:52:54 +02:00
|
|
|
public function markDeleted()
|
|
|
|
{
|
2021-08-29 13:17:27 +02:00
|
|
|
$this->removeUnpaidGatewayFees();
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2020-09-23 12:52:54 +02:00
|
|
|
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-12-03 11:46:36 +01:00
|
|
|
public function handleRestore()
|
2020-12-03 05:20:39 +01:00
|
|
|
{
|
2020-12-03 11:46:36 +01:00
|
|
|
$this->invoice = (new HandleRestore($this->invoice))->run();
|
2020-12-03 05:20:39 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-06-15 01:34:18 +02:00
|
|
|
public function reverseCancellation()
|
|
|
|
{
|
2021-08-29 13:17:27 +02:00
|
|
|
$this->removeUnpaidGatewayFees();
|
|
|
|
|
2020-06-15 01:34:18 +02:00
|
|
|
$this->invoice = (new HandleCancellation($this->invoice))->reverse();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-07-06 01:34:25 +02:00
|
|
|
public function triggeredActions($request)
|
|
|
|
{
|
2022-04-20 03:55:33 +02:00
|
|
|
$this->invoice = (new TriggeredActions($this->invoice->load('invitations'), $request))->run();
|
2020-07-06 01:34:25 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-07-07 14:33:11 +02:00
|
|
|
public function autoBill()
|
|
|
|
{
|
2021-12-03 07:19:24 +01:00
|
|
|
(new AutoBillInvoice($this->invoice, $this->invoice->company->db))->run();
|
2020-07-07 14:33:11 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
public function markViewed()
|
|
|
|
{
|
|
|
|
$this->invoice->last_viewed = Carbon::now()->format('Y-m-d H:i');
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* One liners */
|
|
|
|
public function setDueDate()
|
|
|
|
{
|
2020-09-06 11:38:10 +02:00
|
|
|
if ($this->invoice->due_date != '' || $this->invoice->client->getSetting('payment_terms') == '') {
|
2020-05-28 06:18:34 +02:00
|
|
|
return $this;
|
2020-09-06 11:38:10 +02:00
|
|
|
}
|
2020-02-03 11:33:07 +01:00
|
|
|
|
2020-05-28 06:18:34 +02:00
|
|
|
$this->invoice->due_date = Carbon::parse($this->invoice->date)->addDays($this->invoice->client->getSetting('payment_terms'));
|
2020-09-06 11:38:10 +02:00
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
return $this;
|
|
|
|
}
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2021-05-26 04:37:16 +02:00
|
|
|
public function setReminder($settings = null)
|
|
|
|
{
|
|
|
|
$this->invoice = (new UpdateReminder($this->invoice, $settings))->run();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2020-02-03 11:33:07 +01:00
|
|
|
|
|
|
|
public function setStatus($status)
|
|
|
|
{
|
|
|
|
$this->invoice->status_id = $status;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-10-23 06:18:16 +02:00
|
|
|
public function setCalculatedStatus()
|
|
|
|
{
|
2022-06-21 11:57:17 +02:00
|
|
|
if (round($this->invoice->balance, 2) == 0) {
|
2020-10-23 06:18:16 +02:00
|
|
|
$this->setStatus(Invoice::STATUS_PAID);
|
2020-11-25 15:19:52 +01:00
|
|
|
} elseif ($this->invoice->balance > 0 && $this->invoice->balance < $this->invoice->amount) {
|
2020-10-23 06:18:16 +02:00
|
|
|
$this->setStatus(Invoice::STATUS_PARTIAL);
|
2020-11-25 15:19:52 +01:00
|
|
|
}
|
2020-10-23 06:18:16 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-09-11 02:10:53 +02:00
|
|
|
public function updateStatus()
|
|
|
|
{
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($this->invoice->status_id == Invoice::STATUS_DRAFT) {
|
2021-08-29 13:17:27 +02:00
|
|
|
return $this;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2021-08-29 13:17:27 +02:00
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if (round($this->invoice->balance, 2) == 0) {
|
2021-12-28 10:57:48 +01:00
|
|
|
$this->invoice->status_id = Invoice::STATUS_PAID;
|
2022-06-21 11:57:17 +02:00
|
|
|
} elseif ($this->invoice->balance > 0 && $this->invoice->balance < $this->invoice->amount) {
|
2021-12-28 10:57:48 +01:00
|
|
|
$this->invoice->status_id = Invoice::STATUS_PARTIAL;
|
2020-11-25 15:19:52 +01:00
|
|
|
}
|
2022-07-19 11:36:55 +02:00
|
|
|
elseif ($this->invoice->balance < 0) {
|
|
|
|
$this->invoice->status_id = Invoice::STATUS_SENT;
|
|
|
|
}
|
2020-10-28 11:10:49 +01:00
|
|
|
|
2020-09-11 02:10:53 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-07-15 07:05:02 +02:00
|
|
|
public function toggleFeesPaid()
|
|
|
|
{
|
|
|
|
$this->invoice->line_items = collect($this->invoice->line_items)
|
2020-07-15 08:08:57 +02:00
|
|
|
->map(function ($item) {
|
2020-09-06 11:38:10 +02:00
|
|
|
if ($item->type_id == '3') {
|
|
|
|
$item->type_id = '4';
|
|
|
|
}
|
2020-07-15 07:05:02 +02:00
|
|
|
|
2020-09-06 11:38:10 +02:00
|
|
|
return $item;
|
|
|
|
})->toArray();
|
2020-07-15 07:05:02 +02:00
|
|
|
|
2022-04-01 04:46:55 +02:00
|
|
|
$this->touchPdf();
|
2020-10-10 05:32:10 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function deletePdf()
|
|
|
|
{
|
2021-10-08 07:23:00 +02:00
|
|
|
$this->invoice->load('invitations');
|
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
$this->invoice->invitations->each(function ($invitation) {
|
|
|
|
try {
|
|
|
|
if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
|
|
|
Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
|
|
|
Storage::disk('public')->delete($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf');
|
|
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
nlog($e->getMessage());
|
2021-06-12 13:50:01 +02:00
|
|
|
}
|
|
|
|
});
|
2021-05-24 12:58:37 +02:00
|
|
|
|
2020-07-15 07:05:02 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function removeUnpaidGatewayFees()
|
|
|
|
{
|
2022-03-24 03:11:09 +01:00
|
|
|
$balance = $this->invoice->balance;
|
|
|
|
|
2021-10-24 22:25:14 +02:00
|
|
|
//return early if type three does not exist.
|
2022-06-21 11:57:17 +02:00
|
|
|
if (! collect($this->invoice->line_items)->contains('type_id', 3)) {
|
2021-10-24 22:25:14 +02:00
|
|
|
return $this;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2021-10-24 22:25:14 +02:00
|
|
|
|
2022-03-29 05:13:11 +02:00
|
|
|
$pre_count = count($this->invoice->line_items);
|
|
|
|
|
2020-07-15 07:05:02 +02:00
|
|
|
$this->invoice->line_items = collect($this->invoice->line_items)
|
|
|
|
->reject(function ($item) {
|
2020-09-06 11:38:10 +02:00
|
|
|
return $item->type_id == '3';
|
|
|
|
})->toArray();
|
2020-07-15 07:05:02 +02:00
|
|
|
|
2020-09-11 00:30:12 +02:00
|
|
|
$this->invoice = $this->invoice->calc()->getInvoice();
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2022-03-24 03:11:09 +01:00
|
|
|
/* 24-03-2022 */
|
|
|
|
$new_balance = $this->invoice->balance;
|
|
|
|
|
2022-04-01 04:46:55 +02:00
|
|
|
$post_count = count($this->invoice->line_items);
|
|
|
|
nlog("pre count = {$pre_count} post count = {$post_count}");
|
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if ((int) $pre_count != (int) $post_count) {
|
2022-03-24 03:11:09 +01:00
|
|
|
$adjustment = $balance - $new_balance;
|
|
|
|
|
|
|
|
$this->invoice
|
|
|
|
->client
|
|
|
|
->service()
|
|
|
|
->updateBalance($adjustment * -1)
|
|
|
|
->save();
|
|
|
|
|
|
|
|
$this->invoice
|
|
|
|
->ledger()
|
|
|
|
->updateInvoiceBalance($adjustment * -1, 'Adjustment for removing gateway fee');
|
|
|
|
}
|
|
|
|
|
2020-07-15 07:05:02 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-09-02 03:11:01 +02:00
|
|
|
/*Set partial value and due date to null*/
|
2020-02-03 11:33:07 +01:00
|
|
|
public function clearPartial()
|
|
|
|
{
|
|
|
|
$this->invoice->partial = null;
|
|
|
|
$this->invoice->partial_due_date = null;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-09-02 03:11:01 +02:00
|
|
|
/*Update the partial amount of a invoice*/
|
2020-02-03 11:33:07 +01:00
|
|
|
public function updatePartial($amount)
|
|
|
|
{
|
2022-03-27 08:04:13 +02:00
|
|
|
$this->invoice->partial += $amount;
|
2020-02-03 11:33:07 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-09-11 00:30:12 +02:00
|
|
|
/**
|
2020-10-28 11:10:49 +01:00
|
|
|
* Sometimes we need to refresh the
|
2020-09-11 00:30:12 +02:00
|
|
|
* PDF when it is updated etc.
|
2020-10-28 11:10:49 +01:00
|
|
|
* @return InvoiceService
|
2020-09-11 00:30:12 +02:00
|
|
|
*/
|
2021-06-12 11:40:28 +02:00
|
|
|
public function touchPdf($force = false)
|
2020-09-11 00:30:12 +02:00
|
|
|
{
|
2022-01-10 02:47:16 +01:00
|
|
|
try {
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($force) {
|
2022-01-10 02:47:16 +01:00
|
|
|
$this->invoice->invitations->each(function ($invitation) {
|
2022-06-24 13:15:14 +02:00
|
|
|
CreateEntityPdf::dispatchSync($invitation);
|
2022-01-10 02:47:16 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2021-06-12 11:40:28 +02:00
|
|
|
|
|
|
|
$this->invoice->invitations->each(function ($invitation) {
|
2022-01-10 02:47:16 +01:00
|
|
|
CreateEntityPdf::dispatch($invitation);
|
2021-06-12 11:40:28 +02:00
|
|
|
});
|
2022-06-21 11:57:17 +02:00
|
|
|
} catch (\Exception $e) {
|
|
|
|
nlog('failed creating invoices in Touch PDF');
|
2022-01-10 02:47:16 +01:00
|
|
|
}
|
2020-09-11 00:30:12 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-09-02 03:11:01 +02:00
|
|
|
/*When a reminder is sent we want to touch the dates they were sent*/
|
|
|
|
public function touchReminder(string $reminder_template)
|
|
|
|
{
|
|
|
|
switch ($reminder_template) {
|
|
|
|
case 'reminder1':
|
2021-06-23 06:55:12 +02:00
|
|
|
$this->invoice->reminder1_sent = now();
|
|
|
|
$this->invoice->reminder_last_sent = now();
|
|
|
|
$this->invoice->last_sent_date = now();
|
2020-09-02 03:11:01 +02:00
|
|
|
break;
|
|
|
|
case 'reminder2':
|
2021-06-23 06:55:12 +02:00
|
|
|
$this->invoice->reminder2_sent = now();
|
|
|
|
$this->invoice->reminder_last_sent = now();
|
|
|
|
$this->invoice->last_sent_date = now();
|
2020-09-02 03:11:01 +02:00
|
|
|
break;
|
|
|
|
case 'reminder3':
|
2021-06-23 06:55:12 +02:00
|
|
|
$this->invoice->reminder3_sent = now();
|
|
|
|
$this->invoice->reminder_last_sent = now();
|
|
|
|
$this->invoice->last_sent_date = now();
|
2020-09-02 03:11:01 +02:00
|
|
|
break;
|
2021-06-10 03:15:21 +02:00
|
|
|
case 'endless_reminder':
|
2021-06-23 06:55:12 +02:00
|
|
|
$this->invoice->reminder_last_sent = now();
|
|
|
|
$this->invoice->last_sent_date = now();
|
2021-06-10 03:15:21 +02:00
|
|
|
break;
|
2020-09-02 03:11:01 +02:00
|
|
|
default:
|
2021-06-23 06:55:12 +02:00
|
|
|
$this->invoice->reminder1_sent = now();
|
|
|
|
$this->invoice->reminder_last_sent = now();
|
|
|
|
$this->invoice->last_sent_date = now();
|
2020-09-02 03:11:01 +02:00
|
|
|
break;
|
|
|
|
}
|
2020-09-06 11:38:10 +02:00
|
|
|
|
2020-09-02 03:11:01 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-11-01 08:53:43 +01:00
|
|
|
public function linkEntities()
|
|
|
|
{
|
|
|
|
//set all task.invoice_ids = 0
|
|
|
|
$this->invoice->tasks()->update(['invoice_id' => null]);
|
|
|
|
|
|
|
|
//set all tasks.invoice_ids = x with the current line_items
|
2020-11-25 15:19:52 +01:00
|
|
|
$tasks = collect($this->invoice->line_items)->map(function ($item) {
|
|
|
|
if (isset($item->task_id)) {
|
2020-11-01 08:53:43 +01:00
|
|
|
$item->task_id = $this->decodePrimaryKey($item->task_id);
|
2020-11-25 15:19:52 +01:00
|
|
|
}
|
2020-11-01 08:53:43 +01:00
|
|
|
|
2020-11-25 15:19:52 +01:00
|
|
|
if (isset($item->expense_id)) {
|
2020-11-01 08:53:43 +01:00
|
|
|
$item->expense_id = $this->decodePrimaryKey($item->expense_id);
|
2020-11-25 15:19:52 +01:00
|
|
|
}
|
2020-11-01 08:53:43 +01:00
|
|
|
|
|
|
|
return $item;
|
|
|
|
});
|
|
|
|
|
2020-11-25 15:19:52 +01:00
|
|
|
Task::whereIn('id', $tasks->pluck('task_id'))->update(['invoice_id' => $this->invoice->id]);
|
|
|
|
Expense::whereIn('id', $tasks->pluck('expense_id'))->update(['invoice_id' => $this->invoice->id]);
|
2020-11-01 08:53:43 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-11-04 07:02:15 +01:00
|
|
|
public function fillDefaults()
|
|
|
|
{
|
2021-10-12 11:45:15 +02:00
|
|
|
$this->invoice->load('client.company');
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2020-11-04 09:43:20 +01:00
|
|
|
$settings = $this->invoice->client->getMergedSettings();
|
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if (! $this->invoice->design_id) {
|
2020-11-04 09:43:20 +01:00
|
|
|
$this->invoice->design_id = $this->decodePrimaryKey($settings->invoice_design_id);
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (! isset($this->invoice->footer) || empty($this->invoice->footer)) {
|
2020-11-04 09:43:20 +01:00
|
|
|
$this->invoice->footer = $settings->invoice_footer;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2020-11-04 09:43:20 +01:00
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if (! isset($this->invoice->terms) || empty($this->invoice->terms)) {
|
2020-11-04 09:43:20 +01:00
|
|
|
$this->invoice->terms = $settings->invoice_terms;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2021-01-18 12:08:18 +01:00
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if (! isset($this->invoice->public_notes) || empty($this->invoice->public_notes)) {
|
2021-01-18 12:08:18 +01:00
|
|
|
$this->invoice->public_notes = $this->invoice->client->public_notes;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
|
|
|
|
2021-01-18 21:02:32 +01:00
|
|
|
/* If client currency differs from the company default currency, then insert the client exchange rate on the model.*/
|
2022-06-21 11:57:17 +02:00
|
|
|
if (! isset($this->invoice->exchange_rate) && $this->invoice->client->currency()->id != (int) $this->invoice->company->settings->currency_id) {
|
2021-01-18 21:02:32 +01:00
|
|
|
$this->invoice->exchange_rate = $this->invoice->client->currency()->exchange_rate;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2021-01-18 21:02:32 +01:00
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($settings->counter_number_applied == 'when_saved') {
|
2021-11-30 06:05:15 +01:00
|
|
|
$this->invoice->service()->applyNumber()->save();
|
|
|
|
}
|
|
|
|
|
2020-11-25 15:19:52 +01:00
|
|
|
return $this;
|
2020-11-04 07:02:15 +01:00
|
|
|
}
|
2021-05-26 02:35:39 +02:00
|
|
|
|
2021-08-08 00:40:04 +02:00
|
|
|
public function workFlow()
|
|
|
|
{
|
|
|
|
if ($this->invoice->status_id == Invoice::STATUS_PAID && $this->invoice->client->getSetting('auto_archive_invoice')) {
|
|
|
|
/* Throws: Payment amount xxx does not match invoice totals. */
|
2021-10-07 10:04:33 +02:00
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($this->invoice->trashed()) {
|
2022-03-28 07:36:00 +02:00
|
|
|
return $this;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2021-10-20 09:07:33 +02:00
|
|
|
|
2022-03-24 03:50:55 +01:00
|
|
|
$this->invoice->delete();
|
2021-10-20 09:07:33 +02:00
|
|
|
|
2022-03-24 03:50:55 +01:00
|
|
|
event(new InvoiceWasArchived($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
2022-04-27 01:05:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->invoice->status_id == Invoice::STATUS_CANCELLED && $this->invoice->client->getSetting('auto_archive_invoice_cancelled')) {
|
|
|
|
/* Throws: Payment amount xxx does not match invoice totals. */
|
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($this->invoice->trashed()) {
|
2022-04-27 01:05:16 +02:00
|
|
|
return $this;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2022-04-27 01:05:16 +02:00
|
|
|
|
|
|
|
$this->invoice->delete();
|
|
|
|
|
|
|
|
event(new InvoiceWasArchived($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
2021-10-20 09:07:33 +02:00
|
|
|
}
|
2022-03-24 03:50:55 +01:00
|
|
|
|
2021-08-08 00:40:04 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2022-06-08 12:40:26 +02:00
|
|
|
public function adjustInventory($old_invoice = [])
|
2022-05-31 13:17:18 +02:00
|
|
|
{
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($this->invoice->company->track_inventory) {
|
2022-06-24 13:15:14 +02:00
|
|
|
AdjustProductInventory::dispatchSync($this->invoice->company, $this->invoice, $old_invoice);
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2022-05-31 13:17:18 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2020-02-03 11:33:07 +01:00
|
|
|
/**
|
2020-09-06 11:38:10 +02:00
|
|
|
* Saves the invoice.
|
2020-02-14 04:32:22 +01:00
|
|
|
* @return Invoice object
|
2020-02-03 11:33:07 +01:00
|
|
|
*/
|
|
|
|
public function save() :?Invoice
|
|
|
|
{
|
2021-10-10 11:56:05 +02:00
|
|
|
$this->invoice->saveQuietly();
|
2020-02-03 11:33:07 +01:00
|
|
|
|
2021-10-19 11:04:19 +02:00
|
|
|
return $this->invoice->fresh();
|
2020-02-03 11:33:07 +01:00
|
|
|
}
|
|
|
|
}
|