mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Fixes for edge case when deleting an invoice with a partial payment
This commit is contained in:
parent
6e134098b5
commit
87e3f12920
@ -25,6 +25,10 @@ class HandleRestore extends AbstractService
|
||||
|
||||
private $payment_total = 0;
|
||||
|
||||
private $total_payments = 0;
|
||||
|
||||
private $adjustment_amount = 0;
|
||||
|
||||
public function __construct(Invoice $invoice)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
@ -48,22 +52,63 @@ class HandleRestore extends AbstractService
|
||||
//adjust ledger balance
|
||||
$this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance, "Restored invoice {$this->invoice->number}")->save();
|
||||
|
||||
$this->invoice->client->service()->updateBalance($this->invoice->balance)->save();
|
||||
$this->invoice->client
|
||||
->service()
|
||||
->updateBalance($this->invoice->balance)
|
||||
->updatePaidToDate($this->invoice->paid_to_date)
|
||||
->save();
|
||||
|
||||
$this->windBackInvoiceNumber();
|
||||
|
||||
$this->invoice->is_deleted = false;
|
||||
$this->invoice->save();
|
||||
|
||||
$this->restorePaymentables()
|
||||
->setAdjustmentAmount()
|
||||
->adjustPayments();
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
/* Touches all paymentables as deleted */
|
||||
private function restorePaymentables()
|
||||
{
|
||||
$this->invoice->payments->each(function ($payment) {
|
||||
$payment->paymentables()
|
||||
->where('paymentable_type', '=', 'invoices')
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->update(['deleted_at' => false]);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
private function setAdjustmentAmount()
|
||||
{
|
||||
foreach ($this->invoice->payments as $payment) {
|
||||
$this->adjustment_amount += $payment->paymentables
|
||||
->where('paymentable_type', '=', 'invoices')
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->sum(DB::raw('amount'));
|
||||
|
||||
$this->adjustment_amount += $payment->paymentables
|
||||
->where('paymentable_type', '=', 'invoices')
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->sum(DB::raw('refunded'));
|
||||
}
|
||||
|
||||
$this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function adjustPayments()
|
||||
{
|
||||
//if total payments = adjustment amount - that means we need to delete the payments as well.
|
||||
|
||||
if ($this->adjustment_amount == $this->total_payments) {
|
||||
$this->invoice->payments()->update(['payments.deleted_at' => now(), 'payments.is_deleted' => true]);
|
||||
$this->invoice->payments()->update(['payments.deleted_at' => null, 'payments.is_deleted' => false]);
|
||||
} else {
|
||||
|
||||
//adjust payments down by the amount applied to the invoice payment.
|
||||
@ -79,8 +124,10 @@ class HandleRestore extends AbstractService
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->sum(DB::raw('refunded'));
|
||||
|
||||
$payment->amount -= $payment_adjustment;
|
||||
$payment->applied -= $payment_adjustment;
|
||||
$payment->amount += $payment_adjustment;
|
||||
$payment->applied += $payment_adjustment;
|
||||
$payment->is_deleted = false;
|
||||
$payment->restore();
|
||||
$payment->save();
|
||||
});
|
||||
}
|
||||
|
@ -150,6 +150,8 @@ class DeleteInvoiceTest extends TestCase
|
||||
$this->assertEquals(30000, $invoice->balance);
|
||||
$this->assertEquals(6000, $invoice->paid_to_date);
|
||||
|
||||
//delete the invoice an inspect the balances
|
||||
|
||||
$invoice_repo = new InvoiceRepository();
|
||||
|
||||
$invoice = $invoice_repo->delete($invoice);
|
||||
@ -162,6 +164,24 @@ class DeleteInvoiceTest extends TestCase
|
||||
$this->assertTrue($payment->is_deleted);
|
||||
$this->assertEquals(4, $payment->status_id);
|
||||
|
||||
$client->fresh();
|
||||
|
||||
$this->assertEquals(0, $client->balance);
|
||||
$this->assertEquals(0, $client->paid_to_date);
|
||||
|
||||
//restore the invoice. this should also rehydrate the payments and restore the correct paid to dates on the client record
|
||||
|
||||
$invoice_repo->restore($invoice);
|
||||
$invoice = $invoice->fresh();
|
||||
$client = $client->fresh();
|
||||
$payment = $payment->fresh();
|
||||
|
||||
$this->assertEquals(30000, $invoice->balance);
|
||||
$this->assertEquals(6000, $invoice->paid_to_date);
|
||||
$this->assertEquals(6000, $client->paid_to_date);
|
||||
$this->assertEquals(30000, $client->balance);
|
||||
$this->assertEquals(6000, $payment->amount);
|
||||
$this->assertFalse($payment->is_deleted);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user