Subscriptions v2

This commit is contained in:
David Bomba 2022-12-07 16:45:25 +11:00
parent 02d30ee778
commit 33d4402189
2 changed files with 164 additions and 53 deletions

View File

@ -11,6 +11,7 @@
namespace App\Http\Livewire;
use App\DataMapper\ClientSettings;
use App\Factory\ClientFactory;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
@ -19,15 +20,17 @@ use App\Mail\ContactPasswordlessLogin;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Invoice;
use App\Models\RecurringInvoice;
use App\Models\Subscription;
use App\Repositories\ClientContactRepository;
use App\Repositories\ClientRepository;
use App\Utils\Number;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use App\DataMapper\ClientSettings;
use Livewire\Component;
class BillingPortalPurchasev2 extends Component
@ -179,6 +182,13 @@ class BillingPortalPurchasev2 extends Component
*/
public $campaign;
public $bundle;
public $recurring_products;
public $products;
public $optional_recurring_products;
public $optional_products;
public $total;
public function mount()
{
MultiDB::setDb($this->company->db);
@ -196,46 +206,156 @@ class BillingPortalPurchasev2 extends Component
elseif(strlen($this->subscription->promo_code) == 0 && $this->subscription->promo_discount > 0){
$this->price = $this->subscription->promo_price;
}
$this->recurring_products = $this->subscription->service()->recurring_products();
$this->products = $this->subscription->service()->products();
$this->optional_recurring_products = $this->subscription->service()->optional_recurring_products();
$this->optional_products = $this->subscription->service()->optional_products();
$this->buildBundle();
}
public function updatingData()
public function buildBundle()
{
nlog('updating');
// nlog($this->data);
$this->bundle = collect();
$data = $this->data;
foreach($this->recurring_products as $key => $p)
{
$qty = isset($data[$key]['recurring_qty']) ? $data[$key]['recurring_qty'] : 1;
$total = $p->price * $qty;
$this->bundle->push([
'product' => nl2br(substr($p->notes, 0, 50)),
'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
'total' => $total,
'qty' => $qty,
'is_recurring' => true
]);
}
foreach($this->products as $key => $p)
{
$qty = 1;
$total = $p->price * $qty;
$this->bundle->push([
'product' => nl2br(substr($p->notes, 0, 50)),
'price' => Number::formatMoney($total, $this->subscription->company),
'total' => $total,
'qty' => $qty,
'is_recurring' => false
]);
}
foreach($this->data as $key => $value)
{
if(isset($this->data[$key]['optional_recurring_qty']))
{
$p = $this->optional_recurring_products->first(function ($v,$k) use($key){
return $k == $key;
});
$qty = isset($this->data[$key]['optional_recurring_qty']) ? $this->data[$key]['optional_recurring_qty'] : 0;
$total = $p->price * $qty;
if($qty == 0)
return;
$this->bundle->push([
'product' => nl2br(substr($p->notes, 0, 50)),
'price' => Number::formatMoney($total, $this->subscription->company).' / '. RecurringInvoice::frequencyForKey($this->subscription->frequency_id),
'total' => $total,
'qty' => $qty,
'is_recurring' => true
]);
}
if(isset($this->data[$key]['optional_qty']))
{
$p = $this->optional_products->first(function ($v,$k) use($key){
return $k == $key;
});
$qty = isset($this->data[$key]['optional_qty']) ? $this->data[$key]['optional_qty'] : 0;
$total = $p->price * $qty;
if($qty == 0)
return;
$this->bundle->push([
'product' => nl2br(substr($p->notes, 0, 50)),
'price' => Number::formatMoney($total, $this->subscription->company),
'total' => $total,
'qty' => $qty,
'is_recurring' => false
]);
}
}
$this->total = Number::formatMoney($this->bundle->sum('total'), $this->subscription->company);
return $this;
}
public function updatedData()
{
nlog('updated');
nlog($this->data);
$validatedData = $this->validate();
nlog( $validatedData );
}
public function updating($prop)
{
// $this->resetValidation($prop);
// $this->resetErrorBag($prop);
}
public function updated($propertyName)
{
nlog("validating {$propertyName}");
$this->errors = $this->validateOnly($propertyName);
$x = $this->validateOnly($propertyName, $this->rules(), [], $this->attributes());
nlog($this->errors);
$validatedData = $this->validate();
nlog( $validatedData );
// // $validatedData = $this->validate();
$this->buildBundle();
// $order_validator = Validator::make($this->all(), $this->rules(), [], $this->attributes());
}
public function rules()
{
$rules = [
'email' => ['required', 'email'],
'data' => ['required', 'array'],
'data.*.recurring_qty' => ['required', 'between:100,1000'],
'data.*.optional_recurring_qty' => ['required', 'between:100,1000'],
'data.*.optional_qty' => ['required', 'between:100,1000'],
$rules = [
'data.*.recurring_qty' => 'numeric|between:0,1000',
'data.*.optional_recurring_qty' => 'numeric|between:0,1000',
'data.*.optional_qty' => 'numeric|between:0,1000',
];
return $rules;
}
public function attributes()
{
$attributes = [
'data.*.recurring_qty' => 'recurring_qty',
'data.*.optional_recurring_qty' => 'optional_recurring_qty',
'data.*.optional_qty' => 'optional_qty',
];
return $attributes;
}
public function store()
{
}
/**
* Handle user authentication
*

View File

@ -7,10 +7,12 @@
{{ $subscription->name }}
</h1>
</div>
<form wire:submit.prevent="submit">
<!-- Recurring Plan Products-->
<ul role="list" class="-my-6 divide-y divide-gray-200">
@if(!empty($subscription->recurring_product_ids))
@foreach($subscription->service()->recurring_products() as $index => $product)
@foreach($recurring_products as $index => $product)
<li class="flex py-6">
@if(false)
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200">
@ -32,18 +34,11 @@
<p class="text-gray-500 w-full"></p>
<div class="flex place-content-end">
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
<input wire:model="data.{{ $index }}.recurring_qty" type="text" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0"/>
<input wire:model.debounce.300ms="data.{{ $index }}.recurring_qty" type="text" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0"/>
</div>
@endif
</div>
{{ isset($data[$index]['recurring_qty']) ? $data[$index]['recurring_qty'] : 'merp' }}
@if($errors)
@foreach($errors as $error)
{{ $error }}
@endforeach
@endif
@error('data.{{$index}}.recurring_qty')
@error("data.{$index}.recurring_qty")
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<span class="block sm:inline">{{ $message }} </span>
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
@ -55,7 +50,7 @@
@endif
<!-- One Time Plan Products-->
@if(!empty($subscription->product_ids))
@foreach($subscription->service()->products() as $product)
@foreach($products as $product)
<li class="flex py-6">
@if(false)
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200">
@ -93,7 +88,7 @@
<!-- Optional Recurring Products-->
<ul role="list" class="-my-6 divide-y divide-gray-200">
@if(!empty($subscription->optional_recurring_product_ids))
@foreach($subscription->service()->optional_recurring_products() as $index => $product)
@foreach($optional_recurring_products as $index => $product)
<li class="flex py-6">
@if(false)
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
@ -104,7 +99,7 @@
<div>
<div class="flex justify-between text-base font-medium text-gray-900">
<h3>{!! nl2br($product->notes) !!}</h3>
<p class="ml-0">{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }}</p>
<p class="ml-0">{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }} </p>
</div>
<p class="mt-1 text-sm text-gray-500"></p>
</div>
@ -112,21 +107,22 @@
<p class="text-gray-500 w-full"></p>
<div class="flex place-content-end">
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
<input wire:model="data.{{ $index }}.optional_recurring_qty" type="text" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0"/>
<input wire:model.debounce.300ms="data.{{ $index }}.optional_recurring_qty" type="text" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0"/>
</div>
</div>
@error("data.{$index}.optional_recurring_qty")
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<span class="block sm:inline">{{ isset($data[$index]['optional_recurring_qty']) ? $data[$index]['optional_recurring_qty'] : '' }}</span>
<span class="block sm:inline">{{ $message }} </span>
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
</div>
@enderror
</div>
</li>
@endforeach
@endif
@if(!empty($subscription->optional_product_ids))
@foreach($subscription->service()->optional_products() as $index => $product)
@foreach($optional_products as $index => $product)
<li class="flex py-6">
@if(false)
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
@ -145,13 +141,15 @@
<p class="text-gray-500 w-full"></p>
<div class="flex place-content-end">
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
<input type="text" wire:model="data.{{ $index }}.optional_qty" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0">
<input type="text" wire:model.debounce.300ms="data.{{ $index }}.optional_qty" class="w-1/4 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" placeholder="0">
</div>
</div>
@error("data.{$index}.optional_qty")
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<span class="block sm:inline">{{ isset($data[$index]['optional_qty']) ? $data[$index]['optional_qty'] : '' }}</span>
<span class="block sm:inline">{{ $message }} </span>
<span class="absolute top-0 bottom-0 right-0 px-4 py-3">
</div>
@enderror
</div>
</li>
@endforeach
@ -160,27 +158,20 @@
</div>
</div>
</form>
<div class="col-span-4 bg-blue-500 flex flex-col item-center p-2 h-screen">
<div class="w-full p-4">
<div id="summary" class="px-4 text-white">
<h1 class="font-semibold text-2xl border-b-2 border-gray-200 border-opacity-50 pb-2 text-white">{{ ctrans('texts.order') }}</h1>
@foreach($subscription->service()->recurring_products() as $product)
<div class="flex justify-between mt-1 mb-1">
<span class="font-light text-sm uppercase">{!! nl2br(substr($product->notes, 0, 50)) !!}</span>
<span class="font-semibold text-sm">{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }}</span>
</div>
@foreach($bundle as $item)
<div class="flex justify-between mt-1 mb-1">
<span class="font-light text-sm uppercase">{{$item['product']}} x {{$item['qty']}}</span>
<span class="font-semibold text-sm">{{ $item['price'] }}</span>
</div>
@endforeach
@foreach($subscription->service()->products() as $product)
<div class="flex justify-between mt-1 mb-1">
<span class="font-light text-sm uppercase">{!! nl2br(substr($product->notes, 0, 50)) !!}</span>
<span class="font-semibold text-sm">{{ \App\Utils\Number::formatMoney($product->price, $subscription->company) }}</span>
</div>
@endforeach
@if(!empty($subscription->promo_code) && !$subscription->trial_enabled)
<form wire:submit.prevent="handleCoupon" class="">
@csrf
@ -190,7 +181,7 @@
<div class="relative flex flex-grow items-stretch focus-within:z-10">
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
</div>
<input type="text" wire:model.defer="coupon" class="block w-full rounded-none rounded-l-md border-gray-300 pl-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" placeholder="">
<input type="text" wire:model.debounce.300ms="coupon" class="block w-full rounded-none rounded-l-md border-gray-300 pl-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" placeholder="">
</div>
<button type="button" class="relative -ml-px inline-flex items-center space-x-2 rounded-r-md border border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">
@ -204,7 +195,7 @@
<div class="border-t-2 border-gray-200 border-opacity-50 mt-8">
<div class="flex font-semibold justify-between py-6 text-sm uppercase">
<span>{{ ctrans('texts.total') }}</span>
<span>{{ \App\Utils\Number::formatMoney($price, $subscription->company) }}</span>
<span>{{ $total }}</span>
</div>
<button class="bg-white font-semibold hover:bg-gray-600 py-3 text-sm text-blue-500 uppercase w-full">Checkout</button>
</div>