2020-06-28 00:24:08 +02:00
|
|
|
<?php
|
2020-07-01 03:06:40 +02:00
|
|
|
/**
|
2020-09-06 11:38:10 +02:00
|
|
|
* Invoice Ninja (https://invoiceninja.com).
|
2020-07-01 03:06:40 +02:00
|
|
|
*
|
|
|
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
|
|
*
|
2024-04-12 06:15:41 +02:00
|
|
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
2020-07-01 03:06:40 +02:00
|
|
|
*
|
2021-06-16 08:58:16 +02:00
|
|
|
* @license https://www.elastic.co/licensing/elastic-license
|
2020-07-01 03:06:40 +02:00
|
|
|
*/
|
|
|
|
|
2020-06-28 00:24:08 +02:00
|
|
|
namespace App\Services\Payment;
|
|
|
|
|
2023-10-26 04:57:44 +02:00
|
|
|
use App\Models\BankTransaction;
|
2020-06-28 00:24:08 +02:00
|
|
|
use App\Models\Credit;
|
|
|
|
use App\Models\Invoice;
|
|
|
|
use App\Models\Payment;
|
2022-12-14 06:17:43 +01:00
|
|
|
use Illuminate\Contracts\Container\BindingResolutionException;
|
2020-06-28 00:24:08 +02:00
|
|
|
|
|
|
|
class DeletePayment
|
|
|
|
{
|
2022-12-14 06:17:43 +01:00
|
|
|
private float $_paid_to_date_deleted = 0;
|
2020-06-28 00:24:08 +02:00
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
/**
|
2023-07-26 05:19:13 +02:00
|
|
|
* @param Payment $payment
|
2023-02-16 02:36:09 +01:00
|
|
|
* @return void
|
2022-12-14 06:17:43 +01:00
|
|
|
*/
|
2023-02-16 02:36:09 +01:00
|
|
|
public function __construct(public Payment $payment, private bool $update_client_paid_to_date)
|
|
|
|
{
|
|
|
|
}
|
2020-06-28 00:24:08 +02:00
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
/**
|
2023-07-26 05:19:13 +02:00
|
|
|
* @return Payment
|
2023-02-16 02:36:09 +01:00
|
|
|
* @throws BindingResolutionException
|
2022-12-14 06:17:43 +01:00
|
|
|
*/
|
2020-06-28 00:24:08 +02:00
|
|
|
public function run()
|
|
|
|
{
|
2022-12-14 06:17:43 +01:00
|
|
|
\DB::connection(config('database.default'))->transaction(function () {
|
2022-10-05 02:21:55 +02:00
|
|
|
$this->payment = Payment::withTrashed()->where('id', $this->payment->id)->lockForUpdate()->first();
|
|
|
|
|
2023-01-15 04:59:42 +01:00
|
|
|
if ($this->payment && !$this->payment->is_deleted) {
|
2023-01-14 06:22:26 +01:00
|
|
|
$this->setStatus(Payment::STATUS_CANCELLED) //sets status of payment
|
|
|
|
->updateCreditables() //return the credits first
|
|
|
|
->adjustInvoices()
|
|
|
|
->deletePaymentables()
|
|
|
|
->cleanupPayment()
|
|
|
|
->save();
|
|
|
|
}
|
2023-01-18 06:52:32 +01:00
|
|
|
}, 2);
|
2022-10-05 02:21:55 +02:00
|
|
|
|
|
|
|
return $this->payment;
|
2020-06-28 00:24:08 +02:00
|
|
|
}
|
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
/** @return $this */
|
2020-11-23 13:55:04 +01:00
|
|
|
private function cleanupPayment()
|
|
|
|
{
|
2023-07-31 10:22:34 +02:00
|
|
|
|
2020-11-23 13:55:04 +01:00
|
|
|
$this->payment->is_deleted = true;
|
|
|
|
$this->payment->delete();
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2023-10-26 04:57:44 +02:00
|
|
|
BankTransaction::query()->where('payment_id', $this->payment->id)->cursor()->each(function ($bt) {
|
2024-05-29 05:10:50 +02:00
|
|
|
$bt->invoice_ids = null;
|
2023-07-31 10:22:34 +02:00
|
|
|
$bt->payment_id = null;
|
2023-08-29 05:40:35 +02:00
|
|
|
$bt->status_id = 1;
|
2023-07-31 10:22:34 +02:00
|
|
|
$bt->save();
|
|
|
|
});
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2020-11-23 13:55:04 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
/** @return $this */
|
2020-11-15 22:23:20 +01:00
|
|
|
private function deletePaymentables()
|
|
|
|
{
|
2023-12-15 12:25:52 +01:00
|
|
|
|
|
|
|
$this->payment->paymentables()
|
2024-01-14 05:05:00 +01:00
|
|
|
->each(function ($pp) {
|
2023-12-15 12:25:52 +01:00
|
|
|
$pp->forceDelete();
|
|
|
|
});
|
2020-11-15 22:23:20 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
/** @return $this */
|
2020-06-28 05:05:58 +02:00
|
|
|
private function adjustInvoices()
|
|
|
|
{
|
2022-12-14 06:17:43 +01:00
|
|
|
$this->_paid_to_date_deleted = 0;
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2020-09-06 11:38:10 +02:00
|
|
|
if ($this->payment->invoices()->exists()) {
|
|
|
|
$this->payment->invoices()->each(function ($paymentable_invoice) {
|
2021-04-22 01:35:31 +02:00
|
|
|
$net_deletable = $paymentable_invoice->pivot->amount - $paymentable_invoice->pivot->refunded;
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
$this->_paid_to_date_deleted += $net_deletable;
|
2023-03-11 02:26:56 +01:00
|
|
|
$paymentable_invoice = $paymentable_invoice->fresh();
|
2022-03-09 03:49:31 +01:00
|
|
|
|
2021-09-04 07:51:31 +02:00
|
|
|
nlog("net deletable amount - refunded = {$net_deletable}");
|
2022-06-21 11:57:17 +02:00
|
|
|
|
2024-10-21 08:16:26 +02:00
|
|
|
if($paymentable_invoice->status_id == Invoice::STATUS_CANCELLED){
|
|
|
|
|
|
|
|
$is_trashed = false;
|
|
|
|
|
|
|
|
if($paymentable_invoice->trashed()){
|
|
|
|
$is_trashed = true;
|
|
|
|
$paymentable_invoice->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
$paymentable_invoice->service()
|
|
|
|
->updatePaidToDate($net_deletable * -1)
|
|
|
|
->save();
|
|
|
|
|
|
|
|
$this->payment
|
|
|
|
->client
|
|
|
|
->service()
|
|
|
|
->updatePaidToDate($net_deletable * -1)
|
|
|
|
->save();
|
|
|
|
|
|
|
|
if($is_trashed){
|
|
|
|
$paymentable_invoice->delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
elseif (! $paymentable_invoice->is_deleted) {
|
2022-03-14 10:52:38 +01:00
|
|
|
$paymentable_invoice->restore();
|
|
|
|
|
2021-09-06 03:04:00 +02:00
|
|
|
$paymentable_invoice->service()
|
|
|
|
->updateBalance($net_deletable)
|
|
|
|
->updatePaidToDate($net_deletable * -1)
|
|
|
|
->save();
|
|
|
|
|
|
|
|
$paymentable_invoice->ledger()
|
2023-11-07 11:58:52 +01:00
|
|
|
->updateInvoiceBalance($net_deletable, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}")
|
|
|
|
->save();
|
|
|
|
|
2023-11-07 04:54:44 +01:00
|
|
|
//@todo refactor
|
2023-03-11 02:26:56 +01:00
|
|
|
$this->payment
|
|
|
|
->client
|
|
|
|
->service()
|
2024-01-14 05:05:00 +01:00
|
|
|
->updateBalanceAndPaidToDate($net_deletable, $net_deletable * -1)
|
2023-03-11 02:26:56 +01:00
|
|
|
->save();
|
2021-09-06 03:04:00 +02:00
|
|
|
|
|
|
|
if ($paymentable_invoice->balance == $paymentable_invoice->amount) {
|
|
|
|
$paymentable_invoice->service()->setStatus(Invoice::STATUS_SENT)->save();
|
2023-10-26 04:57:44 +02:00
|
|
|
} elseif($paymentable_invoice->balance == 0) {
|
2023-10-20 07:40:53 +02:00
|
|
|
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PAID)->save();
|
2023-10-26 04:57:44 +02:00
|
|
|
} else {
|
2021-09-06 03:04:00 +02:00
|
|
|
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save();
|
|
|
|
}
|
2022-06-21 11:57:17 +02:00
|
|
|
} else {
|
2022-12-14 06:17:43 +01:00
|
|
|
$paymentable_invoice->restore();
|
2021-09-06 07:08:41 +02:00
|
|
|
$paymentable_invoice->service()
|
|
|
|
->updatePaidToDate($net_deletable * -1)
|
2021-09-06 03:04:00 +02:00
|
|
|
->save();
|
2023-07-14 09:09:23 +02:00
|
|
|
$paymentable_invoice->delete();
|
|
|
|
|
2020-09-06 11:38:10 +02:00
|
|
|
}
|
2020-06-28 05:05:58 +02:00
|
|
|
});
|
|
|
|
}
|
2021-10-26 12:47:28 +02:00
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
//sometimes the payment is NOT created properly, this catches the payment and prevents the paid to date reducing inappropriately.
|
2023-02-16 02:36:09 +01:00
|
|
|
if ($this->update_client_paid_to_date) {
|
2024-10-17 23:54:38 +02:00
|
|
|
|
|
|
|
$reduced_paid_to_date = $this->payment->amount < 0 ? $this->payment->amount * -1 : min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1);
|
|
|
|
|
|
|
|
// $reduced_paid_to_date = min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1);
|
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
$this->payment
|
2024-10-17 23:54:38 +02:00
|
|
|
->client
|
|
|
|
->service()
|
|
|
|
->updatePaidToDate($reduced_paid_to_date)
|
|
|
|
->save();
|
2022-12-14 06:17:43 +01:00
|
|
|
}
|
2024-01-14 05:05:00 +01:00
|
|
|
|
2020-06-28 05:05:58 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
/** @return $this */
|
2020-06-28 05:05:58 +02:00
|
|
|
private function updateCreditables()
|
|
|
|
{
|
2020-09-06 11:38:10 +02:00
|
|
|
if ($this->payment->credits()->exists()) {
|
2023-02-16 02:36:09 +01:00
|
|
|
$this->payment->credits()->where('is_deleted', 0)->each(function ($paymentable_credit) {
|
2021-11-22 11:09:28 +01:00
|
|
|
$multiplier = 1;
|
|
|
|
|
2022-06-21 11:57:17 +02:00
|
|
|
if ($paymentable_credit->pivot->amount < 0) {
|
2022-03-16 03:06:25 +01:00
|
|
|
$multiplier = -1;
|
2022-06-21 11:57:17 +02:00
|
|
|
}
|
2021-11-22 11:09:28 +01:00
|
|
|
|
2021-01-24 07:44:14 +01:00
|
|
|
$paymentable_credit->service()
|
2022-06-21 11:57:17 +02:00
|
|
|
->updateBalance($paymentable_credit->pivot->amount * $multiplier * -1)
|
2024-04-28 07:00:12 +02:00
|
|
|
->updatePaidToDate($paymentable_credit->pivot->amount * $multiplier * -1)
|
2021-01-24 07:44:14 +01:00
|
|
|
->setStatus(Credit::STATUS_SENT)
|
|
|
|
->save();
|
2022-03-01 11:25:18 +01:00
|
|
|
|
2022-03-16 03:06:25 +01:00
|
|
|
$client = $this->payment->client->fresh();
|
|
|
|
|
|
|
|
$client
|
|
|
|
->service()
|
2022-08-22 02:44:36 +02:00
|
|
|
->adjustCreditBalance($paymentable_credit->pivot->amount)
|
2022-03-16 03:06:25 +01:00
|
|
|
->save();
|
2020-06-28 05:05:58 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2022-12-14 06:17:43 +01:00
|
|
|
/**
|
2023-02-16 02:36:09 +01:00
|
|
|
* @param mixed $status
|
|
|
|
* @return $this
|
2022-12-14 06:17:43 +01:00
|
|
|
*/
|
2020-06-28 05:05:58 +02:00
|
|
|
private function setStatus($status)
|
|
|
|
{
|
2020-07-06 13:22:36 +02:00
|
|
|
$this->payment->status_id = Payment::STATUS_CANCELLED;
|
2020-06-28 05:05:58 +02:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
2020-09-06 11:38:10 +02:00
|
|
|
|
2020-06-28 00:24:08 +02:00
|
|
|
/**
|
2020-09-06 11:38:10 +02:00
|
|
|
* Saves the payment.
|
|
|
|
*
|
2020-06-28 00:24:08 +02:00
|
|
|
* @return Payment $payment
|
|
|
|
*/
|
|
|
|
private function save()
|
|
|
|
{
|
|
|
|
$this->payment->save();
|
|
|
|
|
|
|
|
return $this->payment;
|
|
|
|
}
|
|
|
|
}
|