1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-21 08:51:34 +02:00

Merge pull request #5225 from beganovich/v5-2203-billing-portal

(v5) 2203: Billing portal
This commit is contained in:
Benjamin Beganović 2021-03-23 16:24:04 +01:00 committed by GitHub
commit 7b89f1cd1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 45 deletions

View 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',
];
}

View File

@ -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);

View File

@ -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()

View File

@ -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')

View File

@ -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>