1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-21 08:51:34 +02:00

Merge pull request #5501 from turbo124/v5-develop

Fixes for deleting refunded payments.
This commit is contained in:
David Bomba 2021-04-22 10:11:16 +10:00 committed by GitHub
commit b72e6de980
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 219 additions and 13 deletions

View File

@ -1 +1 @@
5.1.49
5.1.50

View File

@ -88,9 +88,9 @@ class OneTimeTokenController extends BaseController
MultiDB::findAndSetDbByCompanyKey($data['company_key']);
$user = User::findOrFail($data['user_id']);
// $user = User::findOrFail($data['user_id']);
Auth::login($user, true);
// Auth::login($user, true);
// Cache::forget($request->input('hash'));

View File

@ -245,21 +245,30 @@ class Invoice extends BaseModel
public function getStatusAttribute()
{
if ($this->status_id == self::STATUS_SENT && $this->due_date > Carbon::now()) {
$due_date = $this->due_date ? Carbon::parse($this->due_date) : false;
$partial_due_date = $this->partial_due_Date ? Carbon::parse($this->partial_due_date) : false;
if ($this->status_id == self::STATUS_SENT && $due_date && $due_date->gt(now())) {
nlog("1 unpaid");
return self::STATUS_UNPAID;
} elseif ($this->status_id == self::STATUS_PARTIAL && $this->partial_due_date > Carbon::now()) {
return self::STATUS_UNPAID;
} elseif ($this->status_id == self::STATUS_SENT && $this->due_date < Carbon::now()) {
} elseif ($this->status_id == self::STATUS_PARTIAL && $partial_due_date && $partial_due_date->gt(now())) {
nlog("2 partial");
return self::STATUS_PARTIAL;
} elseif ($this->status_id == self::STATUS_SENT && $due_date && $due_date->lt(now())) {
nlog("3 overdue");
return self::STATUS_OVERDUE;
} elseif ($this->status_id == self::STATUS_PARTIAL && $this->partial_due_date < Carbon::now()) {
} elseif ($this->status_id == self::STATUS_PARTIAL && $partial_due_date && $partial_due_date->lt(now())) {
nlog("4 overdue");
return self::STATUS_OVERDUE;
} else {
nlog("status id ");
return $this->status_id;
}
}
public function isPayable(): bool
{
if ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) {
return true;
} elseif ($this->status_id == self::STATUS_SENT && $this->is_deleted == false) {

View File

@ -80,19 +80,21 @@ class DeletePayment
$this->payment->invoices()->each(function ($paymentable_invoice) {
$net_deletable = $paymentable_invoice->pivot->amount - $paymentable_invoice->pivot->refunded;
$paymentable_invoice->service()
->updateBalance($paymentable_invoice->pivot->amount)
->updatePaidToDate($paymentable_invoice->pivot->amount * -1)
->updateBalance($net_deletable)
->updatePaidToDate($net_deletable * -1)
->save();
$paymentable_invoice->ledger()
->updateInvoiceBalance($paymentable_invoice->pivot->amount, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}")
->updateInvoiceBalance($net_deletable, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}")
->save();
$paymentable_invoice->client
->service()
->updateBalance($paymentable_invoice->pivot->amount)
->updatePaidToDate($paymentable_invoice->pivot->amount * -1)
->updateBalance($net_deletable)
->updatePaidToDate($net_deletable * -1)
->save();
if ($paymentable_invoice->balance == $paymentable_invoice->amount) {

View File

@ -14,6 +14,7 @@ use App\DataMapper\ClientSettings;
use App\Factory\ClientFactory;
use App\Factory\CreditFactory;
use App\Factory\InvoiceFactory;
use App\Factory\InvoiceItemFactory;
use App\Factory\PaymentFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Models\Client;
@ -1385,4 +1386,99 @@ class PaymentTest extends TestCase
$this->assertEquals(1, $arr['data'][0]['is_deleted']);
}
public function testDeleteRefundedPayment()
{
$this->invoice = null;
$client = ClientFactory::create($this->company->id, $this->user->id);
$client->save();
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
$this->invoice->client_id = $client->id;
$item = InvoiceItemFactory::create();
$item->quantity = 1;
$item->cost = 10;
$item->product_key = 'test';
$item->notes = 'test';
$item->custom_value1 = '';
$item->custom_value2 = '';
$item->custom_value3 = '';
$item->custom_value4 = '';
$line_items[] = $item;
$this->invoice->line_items = $line_items;
$this->invoice->uses_inclusive_taxes = false;
$this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice();
$this->invoice->save();
$this->invoice->service()->markSent()->save();
$this->assertEquals(10, $this->invoice->balance);
$this->assertEquals(10, $this->invoice->client->balance);
$this->invoice->service()->markPaid()->save();
$this->assertEquals(0, $this->invoice->balance);
$this->assertEquals(0, $this->invoice->client->balance);
$this->assertTrue($this->invoice->payments()->exists());
$payment = $this->invoice->payments()->first();
$data = [
'id' => $this->encodePrimaryKey($payment->id),
'amount' => 10,
'date' => '2021/12/12',
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => 10,
],
],
];
$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);
nlog($message);
}
$arr = $response->json();
$response->assertStatus(200);
$this->assertEquals(10, $this->invoice->fresh()->balance);
$this->assertEquals(10, $this->invoice->fresh()->balance);
$data = [
'ids' => [$this->encodePrimaryKey($payment->id)],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/payments/bulk?action=delete', $data);
$this->assertEquals(10, $this->invoice->fresh()->balance);
$this->assertEquals(10, $this->invoice->fresh()->balance);
}
}

View File

@ -18,6 +18,7 @@ use App\Models\Company;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\RecurringInvoice;
use App\Models\Timezone;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
@ -48,6 +49,42 @@ class GeneratesCounterTest extends TestCase
$this->makeTestData();
}
public function testResetCounter()
{
$timezone = Timezone::find(1);
$date_formatted = now($timezone->name)->format('Ymd');
$settings = $this->company->settings;
$settings->invoice_number_pattern = '{$date:Ymd}-{$counter}';
$settings->timezone_id = 1;
$this->company->settings = $settings;
$this->company->save();
$this->client->settings = $settings;
$this->client->save();
$invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh());
$this->assertEquals($date_formatted."-0001", $invoice_number);
$invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh());
$this->assertEquals($date_formatted."-0002", $invoice_number);
$settings->reset_counter_date = now($timezone->name)->format('Y-m-d');
$settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY;
$this->company->settings = $settings;
$this->company->save();
$this->client->settings = $settings;
$this->client->save();
$this->travel(5)->days();
$date_formatted = now($timezone->name)->format('Ymd');
$invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh());
$this->assertEquals($date_formatted."-0001", $invoice_number);
}
public function testHasSharedCounter()
{
$this->assertFalse($this->hasSharedCounter($this->client));
@ -348,6 +385,7 @@ class GeneratesCounterTest extends TestCase
$this->assertEquals($vendor_number, date('Y').'-'.str_pad($vendor->user_id, 2, '0', STR_PAD_LEFT).'-0002');
}
/*
public function testClientNextNumber()

View File

@ -0,0 +1,58 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace Tests\Unit;
use App\Factory\InvoiceItemFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Models\Invoice;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\MockAccountData;
use Tests\TestCase;
/**
* @test
* @covers App\Helpers\Invoice\InvoiceSum
*/
class InvoiceStatusTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public $invoice;
public $invoice_calc;
public $settings;
public function setUp() :void
{
parent::setUp();
$this->makeTestData();
}
public function testSentStatus()
{
$this->invoice->due_date = now()->addMonth();
$this->invoice->status_id = Invoice::STATUS_SENT;
$this->assertEquals(Invoice::STATUS_UNPAID, $this->invoice->getStatusAttribute());
}
public function testPartialStatus()
{
$this->invoice->partial_due_date = now()->addMonth();
$this->invoice->status_id = Invoice::STATUS_SENT;
$this->assertEquals(Invoice::STATUS_SENT, $this->invoice->getStatusAttribute());
}
}

View File

@ -12,6 +12,7 @@ namespace Tests\Unit;
use App\Factory\InvoiceItemFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Models\Invoice;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\MockAccountData;
use Tests\TestCase;
@ -220,4 +221,6 @@ class InvoiceTest extends TestCase
//$this->assertEquals($this->invoice_calc->getTotalTaxes(), 4);
//$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
}
}