mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Support for "Start Free Trial"
This commit is contained in:
parent
85c09ecf11
commit
415ea81eec
@ -12,7 +12,9 @@
|
|||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
use App\Factory\ClientFactory;
|
use App\Factory\ClientFactory;
|
||||||
|
use App\Models\BillingSubscription;
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
|
use App\Models\Invoice;
|
||||||
use App\Repositories\ClientContactRepository;
|
use App\Repositories\ClientContactRepository;
|
||||||
use App\Repositories\ClientRepository;
|
use App\Repositories\ClientRepository;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
@ -21,39 +23,111 @@ use Livewire\Component;
|
|||||||
|
|
||||||
class BillingPortalPurchase extends Component
|
class BillingPortalPurchase extends Component
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Random hash generated by backend to handle the tracking of state.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public $hash;
|
public $hash;
|
||||||
|
|
||||||
public $heading_text = 'Log in';
|
/**
|
||||||
|
* Top level text on the left side of billing page.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $heading_text;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* E-mail address model for user input.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public $email;
|
public $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Password model for user input.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public $password;
|
public $password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of billing subscription.
|
||||||
|
*
|
||||||
|
* @var BillingSubscription
|
||||||
|
*/
|
||||||
public $billing_subscription;
|
public $billing_subscription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of client contact.
|
||||||
|
*
|
||||||
|
* @var null|ClientContact
|
||||||
|
*/
|
||||||
public $contact;
|
public $contact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rules for validating the form.
|
||||||
|
*
|
||||||
|
* @var \string[][]
|
||||||
|
*/
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'email' => ['required', 'email'],
|
'email' => ['required', 'email'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id for CompanyGateway record.
|
||||||
|
*
|
||||||
|
* @var string|integer
|
||||||
|
*/
|
||||||
public $company_gateway_id;
|
public $company_gateway_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id for GatewayType.
|
||||||
|
*
|
||||||
|
* @var string|integer
|
||||||
|
*/
|
||||||
public $payment_method_id;
|
public $payment_method_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of steps that frontend form follows.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
public $steps = [
|
public $steps = [
|
||||||
'passed_email' => false,
|
'passed_email' => false,
|
||||||
'existing_user' => false,
|
'existing_user' => false,
|
||||||
'fetched_payment_methods' => false,
|
'fetched_payment_methods' => false,
|
||||||
'fetched_client' => false,
|
'fetched_client' => false,
|
||||||
|
'show_start_trial' => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of payment methods fetched from client.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
public $methods = [];
|
public $methods = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of \App\Models\Invoice
|
||||||
|
*
|
||||||
|
* @var Invoice
|
||||||
|
*/
|
||||||
public $invoice;
|
public $invoice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coupon model for user input
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
public $coupon;
|
public $coupon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle user authentication
|
||||||
|
*
|
||||||
|
* @return $this|bool|void
|
||||||
|
*/
|
||||||
public function authenticate()
|
public function authenticate()
|
||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
@ -81,6 +155,12 @@ class BillingPortalPurchase extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a blank client. Used for new customers purchasing.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Laracasts\Presenter\Exceptions\PresenterException
|
||||||
|
*/
|
||||||
protected function createBlankClient()
|
protected function createBlankClient()
|
||||||
{
|
{
|
||||||
$company = $this->billing_subscription->company;
|
$company = $this->billing_subscription->company;
|
||||||
@ -98,13 +178,26 @@ class BillingPortalPurchase extends Component
|
|||||||
return $client->contacts->first();
|
return $client->contacts->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetching payment methods from the client.
|
||||||
|
*
|
||||||
|
* @param ClientContact $contact
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
protected function getPaymentMethods(ClientContact $contact): self
|
protected function getPaymentMethods(ClientContact $contact): self
|
||||||
{
|
{
|
||||||
|
if ($this->billing_subscription->trial_enabled) {
|
||||||
|
$this->heading_text = ctrans('texts.plan_trial');
|
||||||
|
$this->steps['show_start_trial'] = true;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
$this->steps['fetched_payment_methods'] = true;
|
$this->steps['fetched_payment_methods'] = true;
|
||||||
|
|
||||||
$this->methods = $contact->client->service()->getPaymentMethods(1000);
|
$this->methods = $contact->client->service()->getPaymentMethods(1000);
|
||||||
|
|
||||||
$this->heading_text = 'Pick a payment method';
|
$this->heading_text = ctrans('texts.payment_methods');
|
||||||
|
|
||||||
Auth::guard('contact')->login($contact);
|
Auth::guard('contact')->login($contact);
|
||||||
|
|
||||||
@ -113,6 +206,13 @@ class BillingPortalPurchase extends Component
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middle method between selecting payment method &
|
||||||
|
* submitting the from to the backend.
|
||||||
|
*
|
||||||
|
* @param $company_gateway_id
|
||||||
|
* @param $gateway_type_id
|
||||||
|
*/
|
||||||
public function handleMethodSelectingEvent($company_gateway_id, $gateway_type_id)
|
public function handleMethodSelectingEvent($company_gateway_id, $gateway_type_id)
|
||||||
{
|
{
|
||||||
$this->company_gateway_id = $company_gateway_id;
|
$this->company_gateway_id = $company_gateway_id;
|
||||||
@ -121,6 +221,11 @@ class BillingPortalPurchase extends Component
|
|||||||
$this->handleBeforePaymentEvents();
|
$this->handleBeforePaymentEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to handle events before payments.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function handleBeforePaymentEvents()
|
public function handleBeforePaymentEvents()
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
@ -144,13 +249,26 @@ class BillingPortalPurchase extends Component
|
|||||||
Cache::put($this->hash, [
|
Cache::put($this->hash, [
|
||||||
'email' => $this->email ?? $this->contact->email,
|
'email' => $this->email ?? $this->contact->email,
|
||||||
'client_id' => $this->contact->client->id,
|
'client_id' => $this->contact->client->id,
|
||||||
'invoice_id' => $this->invoice->id],
|
'invoice_id' => $this->invoice->id,
|
||||||
|
'subscription_id' => $this->billing_subscription->id],
|
||||||
now()->addMinutes(60)
|
now()->addMinutes(60)
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->emit('beforePaymentEventsCompleted');
|
$this->emit('beforePaymentEventsCompleted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method for starting the trial.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function handleTrial()
|
||||||
|
{
|
||||||
|
return $this->billing_subscription->service()->startTrial([
|
||||||
|
'email' => $this->email ?? $this->contact->email,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
if ($this->contact instanceof ClientContact) {
|
if ($this->contact instanceof ClientContact) {
|
||||||
|
@ -38,18 +38,22 @@ class BillingSubscriptionService
|
|||||||
|
|
||||||
// At this point we have some state carried from the billing page
|
// At this point we have some state carried from the billing page
|
||||||
// to this, available as $payment_hash->data->billing_context. Make something awesome ⭐
|
// to this, available as $payment_hash->data->billing_context. Make something awesome ⭐
|
||||||
|
|
||||||
// create client subscription record
|
// create client subscription record
|
||||||
//
|
//
|
||||||
// create recurring invoice if is_recurring
|
// create recurring invoice if is_recurring
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function startTrial(array $data)
|
public function startTrial(array $data)
|
||||||
{
|
{
|
||||||
|
// Redirects from here work just fine. Livewire will respect it.
|
||||||
|
|
||||||
|
// Some magic here..
|
||||||
|
|
||||||
|
return redirect('/trial-started');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createInvoice($data): ?\App\Models\Invoice
|
public function createInvoice($data): ?\App\Models\Invoice
|
||||||
|
@ -32,14 +32,14 @@
|
|||||||
<div class="col-span-12 lg:col-span-6 bg-white lg:shadow-lg lg:h-screen">
|
<div class="col-span-12 lg:col-span-6 bg-white lg:shadow-lg lg:h-screen">
|
||||||
<div class="grid grid-cols-12 flex flex-col p-10 lg:mt-48 lg:ml-16">
|
<div class="grid grid-cols-12 flex flex-col p-10 lg:mt-48 lg:ml-16">
|
||||||
<div class="col-span-12 w-full lg:col-span-6">
|
<div class="col-span-12 w-full lg:col-span-6">
|
||||||
<h2 class="text-2xl font-bold tracking-wide">{{ $heading_text }}</h2>
|
<h2 class="text-2xl font-bold tracking-wide">{{ $heading_text ?? ctrans('texts.login') }}</h2>
|
||||||
@if (session()->has('message'))
|
@if (session()->has('message'))
|
||||||
@component('portal.ninja2020.components.message')
|
@component('portal.ninja2020.components.message')
|
||||||
{{ session('message') }}
|
{{ session('message') }}
|
||||||
@endcomponent
|
@endcomponent
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if($this->steps['fetched_payment_methods'])
|
@if($steps['fetched_payment_methods'])
|
||||||
<div class="flex items-center mt-4 text-sm">
|
<div class="flex items-center mt-4 text-sm">
|
||||||
<form action="{{ route('client.payments.process', ['hash' => $hash, 'sidebar' => 'hidden']) }}"
|
<form action="{{ route('client.payments.process', ['hash' => $hash, 'sidebar' => 'hidden']) }}"
|
||||||
method="post"
|
method="post"
|
||||||
@ -67,6 +67,17 @@
|
|||||||
</button>
|
</button>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@elseif($steps['show_start_trial'])
|
||||||
|
<form wire:submit.prevent="handleTrial" class="mt-8">
|
||||||
|
@csrf
|
||||||
|
<p class="mb-4">Some text about the trial goes here. Details about the days, etc.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="px-3 py-2 border rounded mr-4 hover:border-blue-600">
|
||||||
|
{{ ctrans('texts.trial_call_to_action') }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<form wire:submit.prevent="authenticate" class="mt-8">
|
<form wire:submit.prevent="authenticate" class="mt-8">
|
||||||
@csrf
|
@csrf
|
||||||
|
Loading…
x
Reference in New Issue
Block a user