mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 21:22:58 +01:00
Merge pull request #5501 from turbo124/v5-develop
Fixes for deleting refunded payments.
This commit is contained in:
commit
b72e6de980
@ -1 +1 @@
|
|||||||
5.1.49
|
5.1.50
|
@ -88,9 +88,9 @@ class OneTimeTokenController extends BaseController
|
|||||||
|
|
||||||
MultiDB::findAndSetDbByCompanyKey($data['company_key']);
|
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'));
|
// Cache::forget($request->input('hash'));
|
||||||
|
|
||||||
|
@ -245,21 +245,30 @@ class Invoice extends BaseModel
|
|||||||
|
|
||||||
public function getStatusAttribute()
|
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;
|
return self::STATUS_UNPAID;
|
||||||
} 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->gt(now())) {
|
||||||
return self::STATUS_UNPAID;
|
nlog("2 partial");
|
||||||
} elseif ($this->status_id == self::STATUS_SENT && $this->due_date < Carbon::now()) {
|
return self::STATUS_PARTIAL;
|
||||||
|
} elseif ($this->status_id == self::STATUS_SENT && $due_date && $due_date->lt(now())) {
|
||||||
|
nlog("3 overdue");
|
||||||
return self::STATUS_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;
|
return self::STATUS_OVERDUE;
|
||||||
} else {
|
} else {
|
||||||
|
nlog("status id ");
|
||||||
return $this->status_id;
|
return $this->status_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isPayable(): bool
|
public function isPayable(): bool
|
||||||
{
|
{
|
||||||
|
|
||||||
if ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) {
|
if ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) {
|
||||||
return true;
|
return true;
|
||||||
} elseif ($this->status_id == self::STATUS_SENT && $this->is_deleted == false) {
|
} elseif ($this->status_id == self::STATUS_SENT && $this->is_deleted == false) {
|
||||||
|
@ -80,19 +80,21 @@ class DeletePayment
|
|||||||
|
|
||||||
$this->payment->invoices()->each(function ($paymentable_invoice) {
|
$this->payment->invoices()->each(function ($paymentable_invoice) {
|
||||||
|
|
||||||
|
$net_deletable = $paymentable_invoice->pivot->amount - $paymentable_invoice->pivot->refunded;
|
||||||
|
|
||||||
$paymentable_invoice->service()
|
$paymentable_invoice->service()
|
||||||
->updateBalance($paymentable_invoice->pivot->amount)
|
->updateBalance($net_deletable)
|
||||||
->updatePaidToDate($paymentable_invoice->pivot->amount * -1)
|
->updatePaidToDate($net_deletable * -1)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$paymentable_invoice->ledger()
|
$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();
|
->save();
|
||||||
|
|
||||||
$paymentable_invoice->client
|
$paymentable_invoice->client
|
||||||
->service()
|
->service()
|
||||||
->updateBalance($paymentable_invoice->pivot->amount)
|
->updateBalance($net_deletable)
|
||||||
->updatePaidToDate($paymentable_invoice->pivot->amount * -1)
|
->updatePaidToDate($net_deletable * -1)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
if ($paymentable_invoice->balance == $paymentable_invoice->amount) {
|
if ($paymentable_invoice->balance == $paymentable_invoice->amount) {
|
||||||
|
@ -14,6 +14,7 @@ use App\DataMapper\ClientSettings;
|
|||||||
use App\Factory\ClientFactory;
|
use App\Factory\ClientFactory;
|
||||||
use App\Factory\CreditFactory;
|
use App\Factory\CreditFactory;
|
||||||
use App\Factory\InvoiceFactory;
|
use App\Factory\InvoiceFactory;
|
||||||
|
use App\Factory\InvoiceItemFactory;
|
||||||
use App\Factory\PaymentFactory;
|
use App\Factory\PaymentFactory;
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
@ -1385,4 +1386,99 @@ class PaymentTest extends TestCase
|
|||||||
|
|
||||||
$this->assertEquals(1, $arr['data'][0]['is_deleted']);
|
$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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ use App\Models\Company;
|
|||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
|
use App\Models\Timezone;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@ -48,6 +49,42 @@ class GeneratesCounterTest extends TestCase
|
|||||||
$this->makeTestData();
|
$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()
|
public function testHasSharedCounter()
|
||||||
{
|
{
|
||||||
$this->assertFalse($this->hasSharedCounter($this->client));
|
$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');
|
$this->assertEquals($vendor_number, date('Y').'-'.str_pad($vendor->user_id, 2, '0', STR_PAD_LEFT).'-0002');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
public function testClientNextNumber()
|
public function testClientNextNumber()
|
||||||
|
58
tests/Unit/InvoiceStatusTest.php
Normal file
58
tests/Unit/InvoiceStatusTest.php
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@ namespace Tests\Unit;
|
|||||||
|
|
||||||
use App\Factory\InvoiceItemFactory;
|
use App\Factory\InvoiceItemFactory;
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
|
use App\Models\Invoice;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Tests\MockAccountData;
|
use Tests\MockAccountData;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
@ -220,4 +221,6 @@ class InvoiceTest extends TestCase
|
|||||||
//$this->assertEquals($this->invoice_calc->getTotalTaxes(), 4);
|
//$this->assertEquals($this->invoice_calc->getTotalTaxes(), 4);
|
||||||
//$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
|
//$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user