From 6e134098b53f85db72e0beadac0114ccc116b93c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 19 Aug 2022 12:09:50 +1000 Subject: [PATCH] tests for deleting an invoice --- app/Jobs/Mail/NinjaMailerJob.php | 8 +- app/Services/Invoice/HandleRestore.php | 32 +++++++ tests/Feature/DeleteInvoiceTest.php | 124 +++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 4 deletions(-) diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php index f59f09c8fa13..0f291e22d0de 100644 --- a/app/Jobs/Mail/NinjaMailerJob.php +++ b/app/Jobs/Mail/NinjaMailerJob.php @@ -324,6 +324,10 @@ class NinjaMailerJob implements ShouldQueue if($this->company->is_disabled && !$this->override) return true; + /* To handle spam users we drop all emails from flagged accounts */ + if(Ninja::isHosted() && $this->company->account && $this->company->account->is_flagged) + return true; + /* On the hosted platform we set default contacts a @example.com email address - we shouldn't send emails to these types of addresses */ if(Ninja::isHosted() && $this->nmo->to_user && strpos($this->nmo->to_user->email, '@example.com') !== false) return true; @@ -332,10 +336,6 @@ class NinjaMailerJob implements ShouldQueue if(Ninja::isHosted() && ($this->nmo->settings->email_sending_method == 'gmail' || $this->nmo->settings->email_sending_method == 'office365')) return false; - /* To handle spam users we drop all emails from flagged accounts */ - if(Ninja::isHosted() && $this->company->account && $this->company->account->is_flagged) - return true; - /* On the hosted platform, if the user is over the email quotas, we do not send the email. */ if(Ninja::isHosted() && $this->company->account && $this->company->account->emailQuotaExceeded()) return true; diff --git a/app/Services/Invoice/HandleRestore.php b/app/Services/Invoice/HandleRestore.php index 8001c51556a2..71e5579b2929 100644 --- a/app/Services/Invoice/HandleRestore.php +++ b/app/Services/Invoice/HandleRestore.php @@ -15,6 +15,7 @@ use App\Models\Invoice; use App\Services\AbstractService; use App\Utils\Ninja; use App\Utils\Traits\GeneratesCounter; +use Illuminate\Support\Facades\DB; class HandleRestore extends AbstractService { @@ -57,6 +58,37 @@ class HandleRestore extends AbstractService return $this->invoice; } + 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]); + } else { + + //adjust payments down by the amount applied to the invoice payment. + + $this->invoice->payments->each(function ($payment) { + $payment_adjustment = $payment->paymentables + ->where('paymentable_type', '=', 'invoices') + ->where('paymentable_id', $this->invoice->id) + ->sum(DB::raw('amount')); + + $payment_adjustment -= $payment->paymentables + ->where('paymentable_type', '=', 'invoices') + ->where('paymentable_id', $this->invoice->id) + ->sum(DB::raw('refunded')); + + $payment->amount -= $payment_adjustment; + $payment->applied -= $payment_adjustment; + $payment->save(); + }); + } + + return $this; + } + + private function windBackInvoiceNumber() { $findme = '_'.ctrans('texts.deleted'); diff --git a/tests/Feature/DeleteInvoiceTest.php b/tests/Feature/DeleteInvoiceTest.php index 4ee19d377858..c3204718f551 100644 --- a/tests/Feature/DeleteInvoiceTest.php +++ b/tests/Feature/DeleteInvoiceTest.php @@ -15,6 +15,7 @@ use App\Factory\InvoiceItemFactory; use App\Models\Client; use App\Models\Invoice; use App\Models\Payment; +use App\Repositories\InvoiceRepository; use App\Utils\Traits\MakesHash; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Routing\Middleware\ThrottleRequests; @@ -41,6 +42,129 @@ class DeleteInvoiceTest extends TestCase ); } + public function testDeleteAndRestoreInvoice() + { + //create an invoice for 36000 with a partial of 6000 + + $data = [ + 'name' => 'A Nice Client - About to be deleted', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients', $data); + + $response->assertStatus(200); + + $arr = $response->json(); + + $client_hash_id = $arr['data']['id']; + $client = Client::find($this->decodePrimaryKey($client_hash_id)); + + $this->assertEquals($client->balance, 0); + $this->assertEquals($client->paid_to_date, 0); + + $line_items = []; + + $item = InvoiceItemFactory::create(); + $item->quantity = 1; + $item->cost = 36000; + + $line_items[] = (array) $item; + + $invoice = [ + 'status_id' => 1, + 'number' => '', + 'discount' => 0, + 'is_amount_discount' => 1, + 'po_number' => '3434343', + 'public_notes' => 'notes', + 'is_deleted' => 0, + 'partial' => 6000, + 'custom_value1' => 0, + 'custom_value2' => 0, + 'custom_value3' => 0, + 'custom_value4' => 0, + 'client_id' => $client_hash_id, + 'line_items' => (array) $line_items, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/invoices/', $invoice) + ->assertStatus(200); + + $arr = $response->json(); + + $invoice_one_hashed_id = $arr['data']['id']; + + $invoice = Invoice::find($this->decodePrimaryKey($invoice_one_hashed_id)); + + $invoice = $invoice->service()->markSent()->save(); + + $this->assertEquals(6000, $invoice->partial); + $this->assertEquals(36000, $invoice->amount); + + + // apply a payment of 6000 + + $data = [ + 'amount' => 6000, + 'client_id' => $client->hashed_id, + 'invoices' => [ + [ + 'invoice_id' => $invoice->hashed_id, + 'amount' => 6000, + ], + ], + 'date' => '2019/12/12', + ]; + + try { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/payments?include=invoices', $data); + } catch (ValidationException $e) { + $message = json_decode($e->validator->getMessageBag(), 1); + $this->assertNotNull($message); + } + + $response->assertStatus(200); + + $arr = $response->json(); + + $payment_id = $arr['data']['id']; + + $payment = Payment::withTrashed()->whereId($this->decodePrimaryKey($payment_id))->first(); + + $this->assertEquals(6000, $payment->amount); + $this->assertEquals(6000, $payment->applied); + + $this->assertEquals(6000, $payment->client->paid_to_date); + + $invoice = $invoice->fresh(); + + $this->assertEquals(30000, $invoice->balance); + $this->assertEquals(6000, $invoice->paid_to_date); + + $invoice_repo = new InvoiceRepository(); + + $invoice = $invoice_repo->delete($invoice); + $invoice = $invoice->fresh(); + + $this->assertTrue($invoice->is_deleted); + + $payment = $payment->fresh(); + + $this->assertTrue($payment->is_deleted); + $this->assertEquals(4, $payment->status_id); + + + } + public function testInvoiceDeletionAfterCancellation() { $data = [