From 9332be783106307769bd5bfc31b779bbe54ebd6e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 5 Oct 2023 23:01:00 +1100 Subject: [PATCH 1/6] Fixes for applying payments --- app/Services/Invoice/ApplyPayment.php | 36 ++++++++++++++------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index de4e5791b594..580e6f1cc9ef 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -35,40 +35,41 @@ class ApplyPayment extends AbstractService $amount_paid = $this->payment_amount * -1; - $this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->save(); + $this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->updatePaidToDate($amount_paid*-1)->save(); } elseif ($this->invoice->partial > 0 && $this->invoice->partial > $this->payment_amount) { //partial amount exists, but the amount is less than the partial amount $amount_paid = $this->payment_amount * -1; - $this->invoice->service()->updatePartial($amount_paid)->updateBalance($amount_paid)->save(); + $this->invoice->service()->updatePartial($amount_paid)->updateBalance($amount_paid)->updatePaidToDate($amount_paid*-1)->save(); } elseif ($this->invoice->partial > 0 && $this->invoice->partial < $this->payment_amount) { //partial exists and the amount paid is GREATER than the partial amount $amount_paid = $this->payment_amount * -1; - $this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->save(); + $this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->updatePaidToDate($amount_paid*-1)->save(); } } else { if ($this->payment_amount == $this->invoice->balance) { $amount_paid = $this->payment_amount * -1; - $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid)->save(); + $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid)->updatePaidToDate($amount_paid*-1)->save(); } elseif ($this->payment_amount < $this->invoice->balance) { //partial invoice payment made $amount_paid = $this->payment_amount * -1; - $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->save(); + $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->updatePaidToDate($amount_paid*-1)->save(); } elseif ($this->payment_amount > $this->invoice->balance) { //partial invoice payment made $amount_paid = $this->invoice->balance * -1; - $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid)->save(); + $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid)->updatePaidToDate($amount_paid*-1)->save(); } } + nlog($this->invoice->id. " " . $this->invoice->paid_to_date); $this->payment ->ledger() ->updatePaymentBalance($amount_paid); @@ -81,22 +82,23 @@ class ApplyPayment extends AbstractService ->updateBalance($amount_paid) ->save(); - /* Update Pivot Record amount */ - $this->payment->invoices->each(function ($inv) use ($amount_paid) { - if ($inv->id == $this->invoice->id) { - // $inv->pivot->amount = ($amount_paid * -1); - // $inv->pivot->save(); - //25-06-2023 - $inv->paid_to_date += floatval($amount_paid * -1); - $inv->save(); - } - }); + // /* Update Pivot Record amount */ + // $this->payment->invoices->each(function ($inv) use ($amount_paid) { + // if ($inv->id == $this->invoice->id) { + // // $inv->pivot->amount = ($amount_paid * -1); + // // $inv->pivot->save(); + // //25-06-2023 + // nlog($inv); + // nlog($amount_paid); + // $inv->paid_to_date += floatval($amount_paid * -1); + // $inv->save(); + // } + // }); $this->invoice ->service() ->applyNumber() ->workFlow() - // ->deletePdf() ->save(); return $this->invoice; From 63de5df95eae0c0301d112a910cdb2207fbc9a35 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 6 Oct 2023 13:25:46 +1100 Subject: [PATCH 2/6] Additional tests --- app/Filters/QuoteFilters.php | 6 ++++++ app/Services/Invoice/ApplyPayment.php | 16 ---------------- tests/Feature/RefundTest.php | 13 +++++++++++++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/app/Filters/QuoteFilters.php b/app/Filters/QuoteFilters.php index 26a6b3f0ae2e..0a8c549af609 100644 --- a/app/Filters/QuoteFilters.php +++ b/app/Filters/QuoteFilters.php @@ -112,6 +112,12 @@ class QuoteFilters extends QueryFilters ->orderBy('due_date', 'DESC'); }); } + + if(in_array('convert', $status_parameters)) { + $query->orWhere(function ($q) { + $q->whereNotNull('invoice_id'); + }); + } }); return $this->builder; diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index 580e6f1cc9ef..058d9949c597 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -69,32 +69,16 @@ class ApplyPayment extends AbstractService } } - nlog($this->invoice->id. " " . $this->invoice->paid_to_date); $this->payment ->ledger() ->updatePaymentBalance($amount_paid); - // nlog("updating client balance by amount {$amount_paid}"); - $this->invoice ->client ->service() ->updateBalance($amount_paid) ->save(); - // /* Update Pivot Record amount */ - // $this->payment->invoices->each(function ($inv) use ($amount_paid) { - // if ($inv->id == $this->invoice->id) { - // // $inv->pivot->amount = ($amount_paid * -1); - // // $inv->pivot->save(); - // //25-06-2023 - // nlog($inv); - // nlog($amount_paid); - // $inv->paid_to_date += floatval($amount_paid * -1); - // $inv->save(); - // } - // }); - $this->invoice ->service() ->applyNumber() diff --git a/tests/Feature/RefundTest.php b/tests/Feature/RefundTest.php index 07a423d56ddb..a187fe49cb5d 100644 --- a/tests/Feature/RefundTest.php +++ b/tests/Feature/RefundTest.php @@ -135,6 +135,7 @@ class RefundTest extends TestCase $this->assertEquals(50, $arr['data']['refunded']); $this->assertEquals(Payment::STATUS_REFUNDED, $arr['data']['status_id']); + } /** @@ -289,6 +290,12 @@ class RefundTest extends TestCase $this->assertNotNull($payment->invoices()); $this->assertEquals(1, $payment->invoices()->count()); + + $i = $this->invoice->fresh(); + + $this->assertEquals(0, $i->balance); + $this->assertEquals(round($this->invoice->amount,2), round($i->paid_to_date,2)); + $data = [ 'id' => $this->encodePrimaryKey($payment->id), 'amount' => 50, @@ -309,6 +316,12 @@ class RefundTest extends TestCase ])->post('/api/v1/payments/refund', $data); $response->assertStatus(200); + + $i = $this->invoice->fresh(); + + $this->assertEquals($i->amount, $i->balance); + $this->assertEquals(0, round($i->paid_to_date, 2)); + } /** From f768932b4b4af883bf1ebb4de91f5287b1d1f325 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 6 Oct 2023 14:23:06 +1100 Subject: [PATCH 3/6] updates for exposing pivot deleted_at column --- app/Models/Invoice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 687cde690ebc..c9754a1fc006 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -316,7 +316,7 @@ class Invoice extends BaseModel */ public function payments(): \Illuminate\Database\Eloquent\Relations\MorphToMany { - return $this->morphToMany(Payment::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded')->withTimestamps(); + return $this->morphToMany(Payment::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded', 'deleted_at')->withTimestamps(); } /** From 81098bb33fe312da220e97a4ff8a9872250d783f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 6 Oct 2023 14:23:32 +1100 Subject: [PATCH 4/6] updates for exposing pivot deleted_at column --- app/Models/Payment.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 6df4fbc0dbaf..e264482048eb 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -220,7 +220,7 @@ class Payment extends BaseModel */ public function invoices(): \Illuminate\Database\Eloquent\Relations\MorphToMany { - return $this->morphedByMany(Invoice::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded')->withTimestamps(); + return $this->morphedByMany(Invoice::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded', 'deleted_at')->withTimestamps(); } /** @@ -228,7 +228,7 @@ class Payment extends BaseModel */ public function credits(): \Illuminate\Database\Eloquent\Relations\MorphToMany { - return $this->morphedByMany(Credit::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded')->withTimestamps(); + return $this->morphedByMany(Credit::class, 'paymentable')->withTrashed()->withPivot('amount', 'refunded', 'deleted_at')->withTimestamps(); } /** From 28909b63960a1ff80174fe7b9740545fc8dc4e11 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 7 Oct 2023 08:55:52 +1100 Subject: [PATCH 5/6] Fixes for mailers --- app/Services/Email/EmailMailable.php | 1 + .../portal/ninja2020/components/entity-documents.blade.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Services/Email/EmailMailable.php b/app/Services/Email/EmailMailable.php index 399b0629e90b..8c7c2c5e4362 100644 --- a/app/Services/Email/EmailMailable.php +++ b/app/Services/Email/EmailMailable.php @@ -96,6 +96,7 @@ class EmailMailable extends Mailable $documents = Document::query()->whereIn('id', $this->email_object->documents) ->where('size', '<', $this->max_attachment_size) + ->where('is_public',1) ->cursor() ->map(function ($document) { return Attachment::fromData(fn () => $document->getFile(), $document->name); diff --git a/resources/views/portal/ninja2020/components/entity-documents.blade.php b/resources/views/portal/ninja2020/components/entity-documents.blade.php index 989203b5adcf..ce2c51790418 100644 --- a/resources/views/portal/ninja2020/components/entity-documents.blade.php +++ b/resources/views/portal/ninja2020/components/entity-documents.blade.php @@ -4,7 +4,7 @@

{{ ctrans('texts.attachments') }}:

- @foreach ($entity->documents as $document) + @foreach ($entity->documents()->where('is_public',1)->get() as $document)
@if($entity instanceof App\Models\PurchaseOrder) @endforeach - @foreach ($entity->company->documents as $document) + @foreach ($entity->company->documents()->where('is_public',1)->get() as $document)
@if($entity instanceof App\Models\PurchaseOrder) Date: Sat, 7 Oct 2023 09:13:30 +1100 Subject: [PATCH 6/6] Add tests --- tests/Feature/Payments/DeletePaymentTest.php | 114 +++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 tests/Feature/Payments/DeletePaymentTest.php diff --git a/tests/Feature/Payments/DeletePaymentTest.php b/tests/Feature/Payments/DeletePaymentTest.php new file mode 100644 index 000000000000..59cc6ae490fe --- /dev/null +++ b/tests/Feature/Payments/DeletePaymentTest.php @@ -0,0 +1,114 @@ +faker = \Faker\Factory::create(); + + Model::reguard(); + + $this->makeTestData(); + $this->withoutExceptionHandling(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + } + + public function testRegularPayment() + { + Invoice::factory() + ->count(10) + ->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'client_id' => $this->client->id, + 'amount' => 101, + 'balance' => 101, + 'status_id' => Invoice::STATUS_SENT, + 'paid_to_date' => 0, + ]); + + $i = Invoice::where('amount', 101)->where('status_id', 2)->take(1)->get(); + + $invoices = $i->map(function ($i){ + return [ + 'invoice_id' => $i->hashed_id, + 'amount' => $i->amount, + ]; + })->toArray(); + + $data = [ + 'client_id' => $this->client->hashed_id, + 'amount' => 0, + 'invoices' => $invoices, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/payments/', $data); + + $response->assertStatus(200); + + $arr = $response->json(); + + $i->fresh()->each(function ($i) { + $this->assertEquals(0, $i->balance); + $this->assertEquals(101, $i->paid_to_date); + $this->assertEquals(Invoice::STATUS_PAID, $i->status_id); + }); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/payments/bulk?action=delete', ['ids' => [$arr['data']['id']]]); + + $response->assertStatus(200); + + $i->fresh()->each(function ($i) { + $this->assertEquals(101, $i->balance); + $this->assertEquals(0, $i->paid_to_date); + $this->assertEquals(Invoice::STATUS_SENT, $i->status_id); + }); + + } +} \ No newline at end of file