mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 21:22:58 +01:00
Merge pull request #5225 from beganovich/v5-2203-billing-portal
(v5) 2203: Billing portal
This commit is contained in:
commit
7b89f1cd1e
47
app/DataMapper/Billing/BillingContextMapper.php
Normal file
47
app/DataMapper/Billing/BillingContextMapper.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?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 App\DataMapper\Billing;
|
||||
|
||||
|
||||
class BillingContextMapper
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $billing_subscription_id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $client_id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $invoice_id;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $casts = [
|
||||
'billing_subscription_id' => 'integer',
|
||||
'email' => 'string',
|
||||
'client_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
];
|
||||
}
|
@ -16,6 +16,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Models\BillingSubscription;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
@ -41,7 +42,9 @@ class BillingSubscriptionPurchaseController extends Controller
|
||||
*/
|
||||
private function setLocale(string $locale): void
|
||||
{
|
||||
$record = DB::table('languages')->where('locale', $locale)->first();
|
||||
$record = Cache::get('languages')->filter(function ($item) use ($locale) {
|
||||
return $item->locale == $locale;
|
||||
})->first();
|
||||
|
||||
if ($record) {
|
||||
App::setLocale($record->locale);
|
||||
|
@ -17,6 +17,7 @@ use App\Models\ClientContact;
|
||||
use App\Models\Invoice;
|
||||
use App\Repositories\ClientContactRepository;
|
||||
use App\Repositories\ClientRepository;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@ -138,6 +139,13 @@ class BillingPortalPurchase extends Component
|
||||
*/
|
||||
public $request_data;
|
||||
|
||||
/**
|
||||
* Price of product.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $price;
|
||||
|
||||
/**
|
||||
* Handle user authentication
|
||||
*
|
||||
@ -192,7 +200,11 @@ class BillingPortalPurchase extends Component
|
||||
];
|
||||
|
||||
if (array_key_exists('locale', $this->request_data)) {
|
||||
$record = DB::table('languages')->where('locale', $this->request_data['locale'])->first();
|
||||
$request = $this->request_data;
|
||||
|
||||
$record = Cache::get('languages')->filter(function ($item) use ($request) {
|
||||
return $item->locale == $request['locale'];
|
||||
})->first();
|
||||
|
||||
if ($record) {
|
||||
$data['settings']['language_id'] = (string)$record->id;
|
||||
@ -262,7 +274,7 @@ class BillingPortalPurchase extends Component
|
||||
'client_contact_id' => $this->contact->hashed_id,
|
||||
]],
|
||||
'user_input_promo_code' => $this->coupon,
|
||||
'coupon' => $this->coupon,
|
||||
'coupon' => empty($this->billing_subscription->promo_code) ? '' : $this->coupon,
|
||||
'quantity' => $this->quantity,
|
||||
];
|
||||
|
||||
@ -280,7 +292,7 @@ class BillingPortalPurchase extends Component
|
||||
'client_id' => $this->contact->client->id,
|
||||
'invoice_id' => $this->invoice->id,
|
||||
'quantity' => $this->quantity,
|
||||
'subscription_id' => $this->billing_subscription->id],
|
||||
'subscription_id' => $this->billing_subscription->id,
|
||||
now()->addMinutes(60)
|
||||
);
|
||||
|
||||
@ -296,6 +308,8 @@ class BillingPortalPurchase extends Component
|
||||
{
|
||||
return $this->billing_subscription->service()->startTrial([
|
||||
'email' => $this->email ?? $this->contact->email,
|
||||
'quantity' => $this->quantity,
|
||||
'contact_id' => $this->contact->id,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -311,14 +325,19 @@ class BillingPortalPurchase extends Component
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
// TODO: Dave review.
|
||||
if ($this->quantity >= $this->billing_subscription->max_seats_limit) {
|
||||
if ($this->quantity >= $this->billing_subscription->max_seats_limit && $option == 'increment') {
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
return $option == 'increment'
|
||||
? $this->quantity++
|
||||
: $this->quantity--;
|
||||
if ($option == 'increment') {
|
||||
$this->quantity++;
|
||||
return $this->price = (int)$this->price + $this->billing_subscription->product->price;
|
||||
}
|
||||
|
||||
$this->quantity--;
|
||||
$this->price = (int)$this->price - $this->billing_subscription->product->price;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
@ -2,7 +2,7 @@
|
||||
@section('meta_title', $billing_subscription->product->product_key)
|
||||
|
||||
@section('body')
|
||||
@livewire('billing-portal-purchase', ['billing_subscription' => $billing_subscription, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data])
|
||||
@livewire('billing-portal-purchase', ['billing_subscription' => $billing_subscription, 'contact' => auth('contact')->user(), 'hash' => $hash, 'request_data' => $request_data, 'price' => $billing_subscription->product->price])
|
||||
@stop
|
||||
|
||||
@push('footer')
|
||||
|
@ -13,32 +13,35 @@
|
||||
<span class="text-sm uppercase font-bold">{{ ctrans('texts.price') }}:</span>
|
||||
|
||||
<div class="flex space-x-2">
|
||||
<h1 class="text-2xl font-bold tracking-wide">{{ App\Utils\Number::formatMoney($billing_subscription->product->price, $billing_subscription->company) }}</h1>
|
||||
<h1 class="text-2xl font-bold tracking-wide">{{ App\Utils\Number::formatMoney($price, $billing_subscription->company) }}</h1>
|
||||
|
||||
@if($billing_subscription->per_seat_enabled)
|
||||
<span class="text-sm">/unit</span>
|
||||
@if($billing_subscription->is_recurring)
|
||||
<span class="text-xs uppercase">/ {{ \App\Models\RecurringInvoice::frequencyForKey($billing_subscription->frequency_id) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="flex mt-4 space-x-4 items-center">
|
||||
<span class="text-sm">{{ ctrans('texts.qty') }}</span>
|
||||
<button wire:click="updateQuantity('decrement')" class="bg-gray-100 border rounded p-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-minus">
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button>{{ $quantity }}</button>
|
||||
<button wire:click="updateQuantity('increment')" class="bg-gray-100 border rounded p-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-plus">
|
||||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if($billing_subscription->per_seat_enabled && $billing_subscription->max_seats_limit > 1)
|
||||
<div class="flex mt-4 space-x-4 items-center">
|
||||
<span class="text-sm">{{ ctrans('texts.qty') }}</span>
|
||||
<button wire:click="updateQuantity('decrement')" class="bg-gray-100 border rounded p-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-minus">
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button>{{ $quantity }}</button>
|
||||
<button wire:click="updateQuantity('increment')" class="bg-gray-100 border rounded p-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-plus">
|
||||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(auth('contact')->user())
|
||||
<a href="{{ route('client.invoices.index') }}" class="block mt-16 inline-flex items-center space-x-2">
|
||||
@ -137,22 +140,24 @@
|
||||
</form>
|
||||
@endif
|
||||
|
||||
<div class="relative mt-8">
|
||||
<div class="absolute inset-0 flex items-center">
|
||||
<div class="w-full border-t border-gray-300"></div>
|
||||
@if(!empty($billing_subscription->promo_code) && !$billing_subscription->trial_enabled)
|
||||
<div class="relative mt-8">
|
||||
<div class="absolute inset-0 flex items-center">
|
||||
<div class="w-full border-t border-gray-300"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative flex justify-center text-sm leading-5">
|
||||
<span class="px-2 text-gray-700 bg-white">Have a coupon code?</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative flex justify-center text-sm leading-5">
|
||||
<span class="px-2 text-gray-700 bg-white">Have a coupon code?</span>
|
||||
<div class="flex items-center mt-4">
|
||||
<label class="w-full mr-2">
|
||||
<input type="text" wire:model.lazy="coupon" class="input w-full m-0"/>
|
||||
<small class="block text-gray-900 mt-2">{{ ctrans('texts.billing_coupon_notice') }}</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mt-4">
|
||||
<label class="w-full mr-2">
|
||||
<input type="text" wire:model.lazy="coupon" class="input w-full m-0"/>
|
||||
<small class="block text-gray-900 mt-2">{{ ctrans('texts.billing_coupon_notice') }}</small>
|
||||
</label>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user