diff --git a/app/Services/Invoice/HandleRestore.php b/app/Services/Invoice/HandleRestore.php index 71e5579b2929..a2d0177be8ce 100644 --- a/app/Services/Invoice/HandleRestore.php +++ b/app/Services/Invoice/HandleRestore.php @@ -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(); }); } diff --git a/tests/Feature/DeleteInvoiceTest.php b/tests/Feature/DeleteInvoiceTest.php index c3204718f551..4d48351272fb 100644 --- a/tests/Feature/DeleteInvoiceTest.php +++ b/tests/Feature/DeleteInvoiceTest.php @@ -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); }