From 7973d7c882d4276fec354394fc093849f299d403 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 27 Sep 2023 14:12:03 +1000 Subject: [PATCH] Fixes for refunds with credits present --- app/Http/Controllers/TaskStatusController.php | 9 +- app/Services/Payment/RefundPayment.php | 44 +-- composer.lock | 73 ++--- tests/CreatesApplication.php | 2 + tests/Feature/PaymentTest.php | 17 +- tests/Feature/RefundTest.php | 258 ++++++++++++++---- tests/Integration/CompanyLedgerTest.php | 2 + tests/MockAccountData.php | 83 +++--- 8 files changed, 338 insertions(+), 150 deletions(-) diff --git a/app/Http/Controllers/TaskStatusController.php b/app/Http/Controllers/TaskStatusController.php index ce5f8da05481..836dc9f88a30 100644 --- a/app/Http/Controllers/TaskStatusController.php +++ b/app/Http/Controllers/TaskStatusController.php @@ -73,7 +73,10 @@ class TaskStatusController extends BaseController */ public function create(CreateTaskStatusRequest $request) { - $task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $task_status = TaskStatusFactory::create($user->company()->id, auth()->user()->id); return $this->itemResponse($task_status); } @@ -87,8 +90,10 @@ class TaskStatusController extends BaseController */ public function store(StoreTaskStatusRequest $request) { + /** @var \App\Models\User $user */ + $user = auth()->user(); - $task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); + $task_status = TaskStatusFactory::create($user->company()->id, auth()->user()->id); $task_status->fill($request->all()); $task_status->save(); diff --git a/app/Services/Payment/RefundPayment.php b/app/Services/Payment/RefundPayment.php index b5b67358abcf..3a649d4444dc 100644 --- a/app/Services/Payment/RefundPayment.php +++ b/app/Services/Payment/RefundPayment.php @@ -29,7 +29,9 @@ class RefundPayment private $credit_note; - private $total_refund; + private float $total_refund = 0; + + private float $credits_used = 0; private $gateway_refund_status; @@ -45,8 +47,6 @@ class RefundPayment $this->refund_data = $refund_data; - $this->total_refund = 0; - $this->gateway_refund_status = false; $this->activity_repository = new ActivityRepository(); @@ -56,9 +56,9 @@ class RefundPayment { $this->payment = $this ->calculateTotalRefund() //sets amount for the refund (needed if we are refunding multiple invoices in one payment) + ->updateCreditables() //return the credits first ->processGatewayRefund() //process the gateway refund if needed ->setStatus() //sets status of payment - ->updateCreditables() //return the credits first ->updatePaymentables() //update the paymentable items ->adjustInvoices() ->finalize() @@ -104,12 +104,14 @@ class RefundPayment */ private function processGatewayRefund() { - if ($this->refund_data['gateway_refund'] !== false && $this->total_refund > 0) { + $net_refund = ($this->total_refund - $this->credits_used); + + if ($this->refund_data['gateway_refund'] !== false && $net_refund > 0) { if ($this->payment->company_gateway) { - $response = $this->payment->company_gateway->driver($this->payment->client)->refund($this->payment, $this->total_refund); + $response = $this->payment->company_gateway->driver($this->payment->client)->refund($this->payment, $net_refund); if($response['amount'] ?? false) - $this->total_refund = $response['amount']; + $net_refund = $response['amount']; if($response['voided'] ?? false) { @@ -123,7 +125,7 @@ class RefundPayment })->toArray(); } - $this->payment->refunded += $this->total_refund; + $this->payment->refunded += $net_refund; if ($response['success'] == false) { $this->payment->save(); @@ -132,7 +134,7 @@ class RefundPayment } } } else { - $this->payment->refunded += $this->total_refund; + $this->payment->refunded += $net_refund; } return $this; @@ -227,23 +229,29 @@ class RefundPayment */ private function updateCreditables() { + if ($this->payment->credits()->exists()) { + + $amount_to_refund = $this->total_refund; + //Adjust credits first!!! foreach ($this->payment->credits as $paymentable_credit) { $available_credit = $paymentable_credit->pivot->amount - $paymentable_credit->pivot->refunded; - if ($available_credit > $this->total_refund) { - $paymentable_credit->pivot->refunded += $this->total_refund; + if ($available_credit > $amount_to_refund) { + $paymentable_credit->pivot->refunded += $amount_to_refund; $paymentable_credit->pivot->save(); $paymentable_credit->service() ->setStatus(Credit::STATUS_SENT) - ->updateBalance($this->total_refund) - ->updatePaidToDate($this->total_refund * -1) + ->adjustBalance($amount_to_refund) + ->updatePaidToDate($amount_to_refund * -1) ->save(); - - $this->total_refund = 0; + + $this->credits_used += $amount_to_refund; + $amount_to_refund = 0; + } else { $paymentable_credit->pivot->refunded += $available_credit; $paymentable_credit->pivot->save(); @@ -254,10 +262,12 @@ class RefundPayment ->updatePaidToDate($available_credit * -1) ->save(); - $this->total_refund -= $available_credit; + $this->credits_used += $available_credit; + $amount_to_refund -= $available_credit; + } - if ($this->total_refund == 0) { + if ($amount_to_refund == 0) { break; } } diff --git a/composer.lock b/composer.lock index 2b184a2ecd53..859dfccaa8c8 100644 --- a/composer.lock +++ b/composer.lock @@ -485,16 +485,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.281.13", + "version": "3.281.14", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "5547757d891495713aa7d5770bf04124d48a6ab5" + "reference": "4b5b8aab08ef0add75f086bc03c7651799d187db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5547757d891495713aa7d5770bf04124d48a6ab5", - "reference": "5547757d891495713aa7d5770bf04124d48a6ab5", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/4b5b8aab08ef0add75f086bc03c7651799d187db", + "reference": "4b5b8aab08ef0add75f086bc03c7651799d187db", "shasum": "" }, "require": { @@ -574,9 +574,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.281.13" + "source": "https://github.com/aws/aws-sdk-php/tree/3.281.14" }, - "time": "2023-09-25T18:07:38+00:00" + "time": "2023-09-26T18:15:48+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1353,16 +1353,16 @@ }, { "name": "doctrine/dbal", - "version": "3.6.7", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "8e0e268052b4a8974cb00215bb2892787021614f" + "reference": "00d03067f07482f025d41ab55e4ba0db5eca2cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/8e0e268052b4a8974cb00215bb2892787021614f", - "reference": "8e0e268052b4a8974cb00215bb2892787021614f", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/00d03067f07482f025d41ab55e4ba0db5eca2cdf", + "reference": "00d03067f07482f025d41ab55e4ba0db5eca2cdf", "shasum": "" }, "require": { @@ -1378,9 +1378,9 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.34", + "phpstan/phpstan": "1.10.35", "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.12", + "phpunit/phpunit": "9.6.13", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", "squizlabs/php_codesniffer": "3.7.2", @@ -1446,7 +1446,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.6.7" + "source": "https://github.com/doctrine/dbal/tree/3.7.0" }, "funding": [ { @@ -1462,7 +1462,7 @@ "type": "tidelift" } ], - "time": "2023-09-19T20:15:41+00:00" + "time": "2023-09-26T20:56:55+00:00" }, { "name": "doctrine/deprecations", @@ -4287,16 +4287,16 @@ }, { "name": "laravel/framework", - "version": "v10.24.0", + "version": "v10.25.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "bcebd0a4c015d5c38aeec299d355a42451dd3726" + "reference": "5132dafecbea5825af7cb4d093d4d7df57aecb61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/bcebd0a4c015d5c38aeec299d355a42451dd3726", - "reference": "bcebd0a4c015d5c38aeec299d355a42451dd3726", + "url": "https://api.github.com/repos/laravel/framework/zipball/5132dafecbea5825af7cb4d093d4d7df57aecb61", + "reference": "5132dafecbea5825af7cb4d093d4d7df57aecb61", "shasum": "" }, "require": { @@ -4314,7 +4314,7 @@ "ext-tokenizer": "*", "fruitcake/php-cors": "^1.2", "guzzlehttp/uri-template": "^1.0", - "laravel/prompts": "^0.1", + "laravel/prompts": "^0.1.9", "laravel/serializable-closure": "^1.3", "league/commonmark": "^2.2.1", "league/flysystem": "^3.8.0", @@ -4483,20 +4483,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-09-19T15:25:04+00:00" + "time": "2023-09-26T15:22:05+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.8", + "version": "v0.1.9", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "68dcc65babf92e1fb43cba0b3f78fc3d8002709c" + "reference": "b603410e7af1040aa2d29e0a2cdca570bb63e827" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/68dcc65babf92e1fb43cba0b3f78fc3d8002709c", - "reference": "68dcc65babf92e1fb43cba0b3f78fc3d8002709c", + "url": "https://api.github.com/repos/laravel/prompts/zipball/b603410e7af1040aa2d29e0a2cdca570bb63e827", + "reference": "b603410e7af1040aa2d29e0a2cdca570bb63e827", "shasum": "" }, "require": { @@ -4505,6 +4505,10 @@ "php": "^8.1", "symfony/console": "^6.2" }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, "require-dev": { "mockery/mockery": "^1.5", "pestphp/pest": "^2.3", @@ -4515,6 +4519,11 @@ "ext-pcntl": "Required for the spinner to be animated." }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + } + }, "autoload": { "files": [ "src/helpers.php" @@ -4529,9 +4538,9 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.8" + "source": "https://github.com/laravel/prompts/tree/v0.1.9" }, - "time": "2023-09-19T15:33:56+00:00" + "time": "2023-09-26T13:14:20+00:00" }, { "name": "laravel/serializable-closure", @@ -15037,16 +15046,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.28.0", + "version": "v3.30.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "113e09fea3d2306319ffaa2423fe3de768b28cff" + "reference": "95c64693b2f149966a2bc05a7a4981b0343ea52f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/113e09fea3d2306319ffaa2423fe3de768b28cff", - "reference": "113e09fea3d2306319ffaa2423fe3de768b28cff", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/95c64693b2f149966a2bc05a7a4981b0343ea52f", + "reference": "95c64693b2f149966a2bc05a7a4981b0343ea52f", "shasum": "" }, "require": { @@ -15120,7 +15129,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.28.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.30.0" }, "funding": [ { @@ -15128,7 +15137,7 @@ "type": "github" } ], - "time": "2023-09-22T20:43:40+00:00" + "time": "2023-09-26T22:10:43+00:00" }, { "name": "hamcrest/hamcrest-php", diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php index 4a7b288daa23..a983e3c3f0a2 100644 --- a/tests/CreatesApplication.php +++ b/tests/CreatesApplication.php @@ -16,6 +16,8 @@ trait CreatesApplication { $app = require __DIR__.'/../bootstrap/app.php'; + define('STDIN', fopen("php://stdin", "r")); + $app->make(Kernel::class)->bootstrap(); Hash::setRounds(4); diff --git a/tests/Feature/PaymentTest.php b/tests/Feature/PaymentTest.php index 1dcdd8f49fa9..1ffbb7c460b8 100644 --- a/tests/Feature/PaymentTest.php +++ b/tests/Feature/PaymentTest.php @@ -1310,15 +1310,14 @@ class PaymentTest extends TestCase ]; - try { - $response = $this->withHeaders([ - 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $this->token, - ])->postJson('/api/v1/payments?include=invoices', $data); - } catch (ValidationException $e) { - $message = json_decode($e->validator->getMessageBag(), 1); - $this->assertNotNull($message); - } + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/payments?include=invoices', $data); + + $response->assertStatus(422); + } public function testPaymentWithSameInvoiceMultipleTimes() diff --git a/tests/Feature/RefundTest.php b/tests/Feature/RefundTest.php index f697b2a540b3..07a423d56ddb 100644 --- a/tests/Feature/RefundTest.php +++ b/tests/Feature/RefundTest.php @@ -11,21 +11,22 @@ namespace Tests\Feature; +use Tests\TestCase; +use App\Models\Credit; +use App\Models\Invoice; +use App\Models\Payment; +use Tests\MockAccountData; +use App\Models\ClientContact; use App\Factory\ClientFactory; use App\Factory\CreditFactory; use App\Factory\InvoiceFactory; -use App\Helpers\Invoice\InvoiceSum; -use App\Models\ClientContact; -use App\Models\Invoice; -use App\Models\Payment; use App\Utils\Traits\MakesHash; +use App\Helpers\Invoice\InvoiceSum; use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Support\Facades\Session; use Illuminate\Validation\ValidationException; -use Tests\MockAccountData; -use Tests\TestCase; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @test @@ -37,6 +38,8 @@ class RefundTest extends TestCase use DatabaseTransactions; use MockAccountData; + public $faker; + protected function setUp() :void { parent::setUp(); @@ -53,7 +56,7 @@ class RefundTest extends TestCase $this->makeTestData(); - $this->withoutExceptionHandling(); + // $this->withoutExceptionHandling(); } /** @@ -82,10 +85,10 @@ class RefundTest extends TestCase $this->invoice->save(); - $this->invoice_calc = new InvoiceSum($this->invoice); - $this->invoice_calc->build(); + $invoice_calc = new InvoiceSum($this->invoice); + $invoice_calc->build(); - $this->invoice = $this->invoice_calc->getInvoice(); + $this->invoice = $invoice_calc->getInvoice(); $this->invoice->save(); $data = [ @@ -119,14 +122,12 @@ class RefundTest extends TestCase $response = false; - try { + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/payments/refund', $data); - } catch (ValidationException $e) { - $message = json_decode($e->validator->getMessageBag(), 1); - } + ])->postJson('/api/v1/payments/refund', $data); + $arr = $response->json(); @@ -165,10 +166,10 @@ class RefundTest extends TestCase $this->invoice->save(); - $this->invoice_calc = new InvoiceSum($this->invoice); - $this->invoice_calc->build(); + $invoice_calc = new InvoiceSum($this->invoice); + $invoice_calc->build(); - $this->invoice = $this->invoice_calc->getInvoice(); + $this->invoice = $invoice_calc->getInvoice(); $this->invoice->save(); $this->invoice->setRelation('client', $this->client); @@ -217,23 +218,12 @@ class RefundTest extends TestCase 'date' => '2020/12/12', ]; - $response = false; - - try { $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->post('/api/v1/payments/refund', $data); - } catch (ValidationException $e) { - $message = json_decode($e->validator->getMessageBag(), 1); - - $this->assertNotNull($message); - \Log::error($message); - } - - if ($response) { - $response->assertStatus(302); - } + ])->postJson('/api/v1/payments/refund', $data); + $response->assertStatus(422); + } /** @@ -262,10 +252,10 @@ class RefundTest extends TestCase $this->invoice->save(); - $this->invoice_calc = new InvoiceSum($this->invoice); - $this->invoice_calc->build(); + $invoice_calc = new InvoiceSum($this->invoice); + $invoice_calc->build(); - $this->invoice = $this->invoice_calc->getInvoice(); + $this->invoice = $invoice_calc->getInvoice(); $this->invoice->save(); $data = [ @@ -346,10 +336,10 @@ class RefundTest extends TestCase $this->invoice->save(); - $this->invoice_calc = new InvoiceSum($this->invoice); - $this->invoice_calc->build(); + $invoice_calc = new InvoiceSum($this->invoice); + $invoice_calc->build(); - $this->invoice = $this->invoice_calc->getInvoice(); + $this->invoice = $invoice_calc->getInvoice(); $this->invoice->save(); $data = [ @@ -439,10 +429,10 @@ class RefundTest extends TestCase $this->invoice->save(); - $this->invoice_calc = new InvoiceSum($this->invoice); - $this->invoice_calc->build(); + $invoice_calc = new InvoiceSum($this->invoice); + $invoice_calc->build(); - $this->invoice = $this->invoice_calc->getInvoice(); + $this->invoice = $invoice_calc->getInvoice(); $this->invoice->save(); $data = [ @@ -485,10 +475,10 @@ class RefundTest extends TestCase $this->invoice->save(); - $this->invoice_calc = new InvoiceSum($this->invoice); - $this->invoice_calc->build(); + $invoice_calc = new InvoiceSum($this->invoice); + $invoice_calc->build(); - $this->invoice = $this->invoice_calc->getInvoice(); + $this->invoice = $invoice_calc->getInvoice(); $this->invoice->save(); $data = [ @@ -553,13 +543,13 @@ class RefundTest extends TestCase $this->invoice->line_items = $this->buildLineItems(); $this->invoice->uses_inclusive_taxes = false; - $this->invoice_client_id = $client->id; + $this->invoice->client_id = $client->id; $this->invoice->save(); - $this->invoice_calc = new InvoiceSum($this->invoice); - $this->invoice_calc->build(); + $invoice_calc = new InvoiceSum($this->invoice); + $invoice_calc->build(); - $this->invoice = $this->invoice_calc->getInvoice(); + $this->invoice = $invoice_calc->getInvoice(); $this->invoice->save(); $this->credit = CreditFactory::create($this->company->id, $this->user->id); @@ -650,4 +640,172 @@ class RefundTest extends TestCase } /*Additional scenarios*/ + + public function testRefundsWhenCreditsArePresent() + { + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'status_id' => Invoice::STATUS_SENT, + 'amount' => 1000, + 'balance' => 1000, + ]); + + $c = Credit::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'status_id' => Invoice::STATUS_SENT, + 'amount' => 100, + 'balance' => 100, + ]); + + $data = [ + 'client_id' => $this->client->hashed_id, + 'invoices' => [ + [ + 'invoice_id' => $i->hashed_id, + 'amount' => 1000, + ], + ], + 'credits' => [ + [ + 'credit_id' => $c->hashed_id, + 'amount' => 100, + ], + ], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/payments', $data); + + $arr = $response->json(); + + $response->assertStatus(200); + + $this->assertEquals(0, $c->fresh()->balance); + $this->assertEquals(0, $i->fresh()->balance); + + $payment_id = $arr['data']['id']; + + $refund = [ + 'id' => $payment_id, + 'client_id' => $this->client->hashed_id, + 'amount' => 10, + 'date' => now()->format('Y-m-d'), + 'invoices' => [ + [ + 'invoice_id' => $i->hashed_id, + 'amount' => 10, + ], + ] + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/payments/refund', $refund); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals(0, $arr['data']['refunded']); + + $this->assertEquals(10, $c->fresh()->balance); + $this->assertEquals(10, $i->fresh()->balance); + + } + + public function testRefundsWithSplitCreditAndPaymentRefund() + { + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'status_id' => Invoice::STATUS_SENT, + 'amount' => 1000, + 'balance' => 1000, + ]); + + $c = Credit::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'status_id' => Invoice::STATUS_SENT, + 'amount' => 100, + 'balance' => 100, + ]); + + $data = [ + 'client_id' => $this->client->hashed_id, + 'invoices' => [ + [ + 'invoice_id' => $i->hashed_id, + 'amount' => 1000, + ], + ], + 'credits' => [ + [ + 'credit_id' => $c->hashed_id, + 'amount' => 100, + ], + ], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/payments', $data); + + $arr = $response->json(); + + $response->assertStatus(200); + + $this->assertEquals(0, $c->fresh()->balance); + $this->assertEquals(0, $i->fresh()->balance); + + $payment_id = $arr['data']['id']; + $payment = Payment::find($this->decodePrimaryKey($payment_id)); + + $this->assertEquals(900, $payment->amount); + $this->assertEquals(900, $payment->applied); + $this->assertEquals(0, $payment->refunded); + + $refund = [ + 'id' => $payment_id, + 'client_id' => $this->client->hashed_id, + 'amount' => 200, + 'date' => now()->format('Y-m-d'), + 'invoices' => [ + [ + 'invoice_id' => $i->hashed_id, + 'amount' => 200, + ], + ] + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/payments/refund', $refund); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals(100, $arr['data']['refunded']); + + $this->assertEquals(100, $c->fresh()->balance); + $this->assertEquals(200, $i->fresh()->balance); + + $this->assertEquals(900, $payment->fresh()->amount); + $this->assertEquals(900, $payment->fresh()->applied); + $this->assertEquals(100, $payment->fresh()->refunded); + + } + } diff --git a/tests/Integration/CompanyLedgerTest.php b/tests/Integration/CompanyLedgerTest.php index 8a4927886015..789d13ae8a62 100644 --- a/tests/Integration/CompanyLedgerTest.php +++ b/tests/Integration/CompanyLedgerTest.php @@ -43,6 +43,8 @@ class CompanyLedgerTest extends TestCase public $account; + public $faker; + protected function setUp() :void { parent::setUp(); diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 96dbc6433ee8..25eef773c06a 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -11,57 +11,58 @@ namespace Tests; -use App\DataMapper\ClientRegistrationFields; -use App\DataMapper\ClientSettings; -use App\DataMapper\CompanySettings; -use App\Factory\CompanyUserFactory; -use App\Factory\CreditFactory; -use App\Factory\InvoiceFactory; -use App\Factory\InvoiceInvitationFactory; -use App\Factory\InvoiceItemFactory; -use App\Factory\InvoiceToRecurringInvoiceFactory; -use App\Factory\PurchaseOrderFactory; -use App\Helpers\Invoice\InvoiceSum; -use App\Jobs\Company\CreateCompanyTaskStatuses; -use App\Models\Account; -use App\Models\BankIntegration; -use App\Models\BankTransaction; -use App\Models\BankTransactionRule; +use App\Models\Task; +use App\Models\User; +use App\Models\Quote; use App\Models\Client; -use App\Models\ClientContact; -use App\Models\Company; -use App\Models\CompanyGateway; -use App\Models\CompanyToken; use App\Models\Credit; -use App\Models\CreditInvitation; +use App\Models\Vendor; +use App\Models\Account; +use App\Models\Company; use App\Models\Expense; -use App\Models\ExpenseCategory; -use App\Models\GroupSetting; -use App\Models\InvoiceInvitation; use App\Models\Payment; use App\Models\Product; use App\Models\Project; -use App\Models\PurchaseOrderInvitation; -use App\Models\Quote; +use App\Models\TaxRate; +use App\Models\Scheduler; +use App\Models\TaskStatus; +use App\Utils\TruthSource; +use App\Models\CompanyToken; +use App\Models\GroupSetting; +use App\Models\ClientContact; +use App\Models\VendorContact; +use App\Factory\CreditFactory; +use App\Models\CompanyGateway; +use App\Models\RecurringQuote; +use Illuminate\Support\Carbon; +use App\Factory\InvoiceFactory; +use App\Models\BankIntegration; +use App\Models\BankTransaction; +use App\Models\ExpenseCategory; use App\Models\QuoteInvitation; +use App\Utils\Traits\MakesHash; +use App\Models\CreditInvitation; use App\Models\RecurringExpense; use App\Models\RecurringInvoice; -use App\Models\RecurringQuote; -use App\Models\Scheduler; -use App\Models\Task; -use App\Models\TaskStatus; -use App\Models\TaxRate; -use App\Models\User; -use App\Models\Vendor; -use App\Models\VendorContact; -use App\Utils\Traits\GeneratesCounter; -use App\Utils\Traits\MakesHash; -use App\Utils\TruthSource; -use Illuminate\Support\Carbon; -use Illuminate\Support\Facades\Cache; +use App\Models\InvoiceInvitation; +use App\DataMapper\ClientSettings; +use App\DataMapper\CompanySettings; +use App\Factory\CompanyUserFactory; +use App\Factory\InvoiceItemFactory; +use App\Helpers\Invoice\InvoiceSum; +use App\Models\BankTransactionRule; use Illuminate\Support\Facades\Hash; +use App\Factory\PurchaseOrderFactory; +use Illuminate\Support\Facades\Cache; +use App\Utils\Traits\GeneratesCounter; use Illuminate\Support\Facades\Schema; +use App\Models\PurchaseOrderInvitation; +use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Storage; +use App\Factory\InvoiceInvitationFactory; +use App\DataMapper\ClientRegistrationFields; +use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\Factory\InvoiceToRecurringInvoiceFactory; /** * Class MockAccountData. @@ -200,7 +201,9 @@ trait MockAccountData /* Warm up the cache !*/ $cached_tables = config('ninja.cached_tables'); - $this->artisan('db:seed --force'); + Artisan::call('db:seed', [ + '--force' => true + ]); foreach ($cached_tables as $name => $class) { // check that the table exists in case the migration is pending