Fixes for edge case when deleting an invoice with a partial payment

This commit is contained in:
David Bomba 2022-08-19 12:48:58 +10:00
parent 6e134098b5
commit 87e3f12920
2 changed files with 71 additions and 4 deletions

View File

@ -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();
});
}

View File

@ -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);
}