Refactor subscription invoices to use standard allow temporary invoice numbers until they are confirmed

This commit is contained in:
David Bomba 2022-12-20 21:46:20 +11:00
parent 971787161c
commit 13f8aa2140
12 changed files with 146 additions and 28 deletions

View File

@ -58,7 +58,7 @@ class ContactRegisterController extends Controller
Auth::guard('contact')->loginUsingId($client_contact->id, true);
return redirect()->intended('client.dashboard');
return redirect()->intended(route('client.dashboard'));
}
private function getClient(array $data)

View File

@ -15,6 +15,7 @@ use App\DataMapper\ClientSettings;
use App\Factory\ClientFactory;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Jobs\Subscription\CleanStaleInvoiceOrder;
use App\Libraries\MultiDB;
use App\Mail\ContactPasswordlessLogin;
use App\Mail\Subscription\OtpCode;
@ -533,6 +534,8 @@ class BillingPortalPurchasev2 extends Component
->adjustInventory()
->save();
CleanStaleInvoiceOrder::dispatch($this->invoice->id, $this->company->db)->delay(600);
Cache::put($this->hash, [
'subscription_id' => $this->subscription->id,
'email' => $this->email ?? $this->contact->email,

View File

@ -0,0 +1,55 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Jobs\Subscription;
use App\Libraries\MultiDB;
use App\Models\Invoice;
use App\Repositories\InvoiceRepository;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class CleanStaleInvoiceOrder implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @param int invoice_id
* @param string $db
*/
public function __construct(private int $invoice_id, private string $db){}
/**
* @param InvoiceRepository $repo
* @return void
*/
public function handle(InvoiceRepository $repo) : void
{
MultiDB::setDb($this->db);
$invoice = Invoice::withTrashed()->find($this->invoice_id);
if($invoice->is_proforma){
$invoice->is_proforma = false;
$repo->delete($invoice);
}
}
public function failed($exception = null)
{
}
}

View File

@ -129,6 +129,7 @@ class Company extends BaseModel
'invoice_task_lock',
'convert_payment_currency',
'convert_expense_currency',
'notify_vendor_when_paid',
];
protected $hidden = [
@ -138,6 +139,7 @@ class Company extends BaseModel
];
protected $casts = [
'is_proforma' => 'bool',
'country_id' => 'string',
'custom_fields' => 'object',
'settings' => 'object',

View File

@ -325,15 +325,6 @@ class BaseDriver extends AbstractPaymentDriver
$invoice->service()->toggleFeesPaid()->save();
}
$transaction = [
'invoice' => $invoice->transaction_event(),
'payment' => [],
'client' => $invoice->client->transaction_event(),
'credit' => [],
'metadata' => [],
];
// TransactionLog::dispatch(TransactionEvent::INVOICE_FEE_APPLIED, $transaction, $invoice->company->db);
});
}

View File

@ -42,9 +42,11 @@ class ApplyNumber extends AbstractService
switch ($this->client->getSetting('counter_number_applied')) {
case 'when_saved':
nlog("when saved");
$this->trySaving();
break;
case 'when_sent':
nlog("when sent");
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
$this->trySaving();
}

View File

@ -82,9 +82,6 @@ class MarkInvoiceDeleted extends AbstractService
{
//if total payments = adjustment amount - that means we need to delete the payments as well.
nlog($this->adjustment_amount);
nlog($this->total_payments);
if ($this->adjustment_amount == $this->total_payments)
$this->invoice->payments()->update(['payments.deleted_at' => now(), 'payments.is_deleted' => true]);

View File

@ -80,11 +80,19 @@ class UpdateInvoicePayment
->clearPartial()
->updateStatus()
->touchPdf()
->workFlow()
->save();
$invoice->service()
->workFlow()
->save();
if($invoice->is_proforma)
{
$invoice->number = '';
$invoice->is_proforma = false;
$invoice->service()
->applyNumber()
->save();
}
/* Updates the company ledger */
$this->payment
@ -101,17 +109,6 @@ class UpdateInvoicePayment
$this->payment->applied += $paid_amount;
$transaction = [
'invoice' => $invoice->transaction_event(),
'payment' => $this->payment->transaction_event(),
'client' => $client->transaction_event(),
'credit' => [],
'metadata' => [],
];
// TransactionLog::dispatch(TransactionEvent::GATEWAY_PAYMENT_MADE, $transaction, $invoice->company->db);
});
/* Remove the event updater from within the loop to prevent race conditions */

View File

@ -714,7 +714,8 @@ class SubscriptionService
$invoice = InvoiceFactory::create($this->subscription->company_id, $this->subscription->user_id);
$invoice->subscription_id = $this->subscription->id;
$invoice->client_id = $client_id;
$invoice->is_proforma = true;
$invoice->number = ctrans('texts.subscription') . "_" . now()->format('Y-m-d') . "_" . rand(0,100000);
$line_items = $bundle->map(function ($item){
$line_item = new InvoiceItem;

View File

@ -193,6 +193,7 @@ class CompanyTransformer extends EntityTransformer
'invoice_task_lock' => (bool) $company->invoice_task_lock,
'convert_payment_currency' => (bool) $company->convert_payment_currency,
'convert_expense_currency' => (bool) $company->convert_expense_currency,
'notify_vendor_when_paid' => (bool) $company->notify_vendor_when_paid,
];
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('companies', function (Blueprint $table)
{
$table->boolean('notify_vendor_when_paid')->default(false);
});
Schema::table('invoices', function (Blueprint $table)
{
$table->boolean('is_proforma')->default(false);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
};

View File

@ -0,0 +1,31 @@
@extends('portal.ninja2020.layout.clean')
@section('meta_title', ctrans('texts.error'))
@section('body')
<div class="flex h-screen">
<div class="m-auto md:w-1/2 lg:w-1/2">
<div class="flex flex-col items-center">
@if($account && !$account->isPaid())
<div>
<img src="{{ asset('images/invoiceninja-black-logo-2.png') }}"
class="border-b border-gray-100 h-18 pb-4" alt="Invoice Ninja logo">
</div>
@elseif(isset($company) && !is_null($company))
<div>
<img src="{{ $company->present()->logo() }}"
class="mx-auto border-b border-gray-100 h-18 pb-4" alt="{{ $company->present()->name() }} logo">
</div>
@endif
<h1 class="text-center text-3xl mt-10">{{ ctrans("texts.subscription_blocked_title") }}</h1>
<p class="text-center opacity-75 mt-10">{{ ctrans('texts.subscription_blocked') }}</p>
</div>
</div>
</div>
@stop
@push('footer')
@endpush