mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 00:54:29 -04:00
Invoice Cancellation (#3605)
* Ensure release build sets correct file and directory permissions * Invoice Cancellation * Invoice Cancellations
This commit is contained in:
parent
bfc434071f
commit
213df6451f
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -30,7 +30,9 @@ jobs:
|
||||
php artisan optimize
|
||||
php artisan storage:link
|
||||
sudo php artisan cache:clear
|
||||
|
||||
sudo find ./ -type f -exec chmod 644 {} \;
|
||||
sudo find ./ -type d -exec chmod 755 {} \;
|
||||
|
||||
- name: Prepare JS/CSS assets
|
||||
run: |
|
||||
npm i
|
||||
|
@ -677,6 +677,11 @@ class InvoiceController extends BaseController
|
||||
}
|
||||
break;
|
||||
case 'cancel':
|
||||
$invoice = $invoice->service()->handleCancellation()->save();
|
||||
|
||||
if(!$bulk){
|
||||
$this->itemResponse($invoice);
|
||||
}
|
||||
break;
|
||||
case 'reverse':
|
||||
$invoice = $invoice->service()->handleReversal()->save();
|
||||
|
59
app/Services/Invoice/HandleCancellation.php
Normal file
59
app/Services/Invoice/HandleCancellation.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Services\Invoice;
|
||||
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\CreditFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Paymentable;
|
||||
use App\Services\AbstractService;
|
||||
use App\Services\Client\ClientService;
|
||||
use App\Services\Payment\PaymentService;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
|
||||
class HandleCancellation extends AbstractService
|
||||
{
|
||||
use GeneratesCounter;
|
||||
|
||||
private $invoice;
|
||||
|
||||
public function __construct(Invoice $invoice)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
/* Check again!! */
|
||||
if(!$this->invoice->invoiceCancellable($this->invoice))
|
||||
return $this->invoice;
|
||||
|
||||
$adjustment = $this->invoice->balance*-1;
|
||||
//set invoice balance to 0
|
||||
$this->invoice->ledger()->updateInvoiceBalance($adjustment, "Invoice cancellation");
|
||||
|
||||
$this->invoice->balance = 0;
|
||||
$this->invoice = $this->invoice->service()->setStatus(Invoice::STATUS_CANCELLED)->save();
|
||||
|
||||
//adjust client balance
|
||||
$this->invoice->client->service()->updateBalance($adjustment)->save();
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class HandleReversal extends AbstractService
|
||||
$credit->service()->markSent()->save();
|
||||
}
|
||||
/* Set invoice balance to 0 */
|
||||
$this->invoice->ledger()->updateInvoiceBalance($balance_remaining, $notes)->save();
|
||||
$this->invoice->ledger()->updateInvoiceBalance($balance_remaining*-1, $notes)->save();
|
||||
|
||||
$this->invoice->balance= 0;
|
||||
|
||||
|
@ -18,6 +18,7 @@ use App\Services\Invoice\ApplyNumber;
|
||||
use App\Services\Invoice\ApplyPayment;
|
||||
use App\Services\Invoice\CreateInvitations;
|
||||
use App\Services\Invoice\GetInvoicePdf;
|
||||
use App\Services\Invoice\HandleCancellation;
|
||||
use App\Services\Invoice\HandleReversal;
|
||||
use App\Services\Invoice\MarkInvoicePaid;
|
||||
use App\Services\Invoice\MarkSent;
|
||||
@ -123,6 +124,14 @@ class InvoiceService
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function handleCancellation()
|
||||
{
|
||||
$this->invoice = (new HandleCancellation($this->invoice))->run();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function markViewed()
|
||||
{
|
||||
$this->invoice->last_viewed = Carbon::now()->format('Y-m-d H:i');
|
||||
|
@ -28,7 +28,7 @@ trait ActionsInvoice
|
||||
public function invoiceCancellable($invoice) :bool
|
||||
{
|
||||
|
||||
if($invoice->status_id == Invoice::STATUS_PARTIAL && $invoice->is_deleted == false && $invoice->deleted_at == NULL)
|
||||
if(($invoice->status_id == Invoice::STATUS_SENT || $invoice->status_id == Invoice::STATUS_PARTIAL) && $invoice->is_deleted == false && $invoice->deleted_at == NULL)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
72
tests/Feature/CancelInvoiceTest.php
Normal file
72
tests/Feature/CancelInvoiceTest.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Factory\CreditFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Listeners\Credit\CreateCreditInvitation;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Paymentable;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Foundation\Testing\WithFaker;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers App\Services\Invoice\HandleCancellation
|
||||
*/
|
||||
|
||||
class CancelInvoiceTest extends TestCase
|
||||
{
|
||||
use MakesHash;
|
||||
use DatabaseTransactions;
|
||||
use MockAccountData;
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
$this->faker = \Faker\Factory::create();
|
||||
|
||||
Model::reguard();
|
||||
|
||||
$this->makeTestData();
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
}
|
||||
|
||||
public function testCancelInvoice()
|
||||
{
|
||||
$this->assertTrue($this->invoice->invoiceCancellable($this->invoice));
|
||||
|
||||
$client_balance = $this->client->balance;
|
||||
$invoice_balance = $this->invoice->balance;
|
||||
|
||||
$this->assertEquals(Invoice::STATUS_SENT, $this->invoice->status_id);
|
||||
|
||||
$this->invoice->service()->handleCancellation()->save();
|
||||
|
||||
$this->assertEquals(0, $this->invoice->balance);
|
||||
$this->assertEquals($this->client->balance, ($client_balance - $invoice_balance));
|
||||
$this->assertNotEquals($client_balance, $this->client->balance);
|
||||
$this->assertEquals(Invoice::STATUS_CANCELLED, $this->invoice->status_id);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ class InvoiceActionsTest extends TestCase
|
||||
{
|
||||
$this->assertTrue($this->invoiceDeletable($this->invoice));
|
||||
$this->assertTrue($this->invoiceReversable($this->invoice));
|
||||
$this->assertFalse($this->invoiceCancellable($this->invoice));
|
||||
$this->assertTrue($this->invoiceCancellable($this->invoice));
|
||||
}
|
||||
|
||||
public function testInvoiceIsReversable()
|
||||
|
Loading…
x
Reference in New Issue
Block a user