Working on v3

This commit is contained in:
David Bomba 2024-11-14 16:23:17 +11:00
parent 8b8d20837f
commit 4837bd210e
15 changed files with 172 additions and 108 deletions

View File

@ -77,7 +77,6 @@ class SubscriptionPurchaseController extends Controller
public function v3(Subscription $subscription, Request $request) public function v3(Subscription $subscription, Request $request)
{ {
// Todo: Prerequirement checks for subscription.
return view('billing-portal.v3.index', [ return view('billing-portal.v3.index', [
'subscription' => $subscription, 'subscription' => $subscription,

View File

@ -88,7 +88,7 @@ class Login extends Component
auth()->guard('contact')->loginUsingId($contact->id, true); auth()->guard('contact')->loginUsingId($contact->id, true);
$this->dispatch('purchase.context', property: 'contact', value: $contact); // $this->dispatch('purchase.context', property: 'contact', value: $contact);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }
@ -96,6 +96,7 @@ class Login extends Component
{ {
$code = rand(100000, 999999); $code = rand(100000, 999999);
$email_hash = "subscriptions:otp:{$this->email}"; $email_hash = "subscriptions:otp:{$this->email}";
$contact = auth()->guard('contact')->user();
Cache::put($email_hash, $code, 600); Cache::put($email_hash, $code, 600);
@ -103,7 +104,7 @@ class Login extends Component
$cc->email = $this->email; $cc->email = $this->email;
$nmo = new NinjaMailerObject(); $nmo = new NinjaMailerObject();
$nmo->mailable = new OtpCode($this->subscription()->company, $this->context['contact'] ?? null, $code); $nmo->mailable = new OtpCode($this->subscription()->company, $contact ?? null, $code);
$nmo->company = $this->subscription()->company; $nmo->company = $this->subscription()->company;
$nmo->settings = $this->subscription()->company->settings; $nmo->settings = $this->subscription()->company->settings;
$nmo->to_user = $cc; $nmo->to_user = $cc;
@ -140,7 +141,7 @@ class Login extends Component
if ($contact) { if ($contact) {
auth()->guard('contact')->loginUsingId($contact->id, true); auth()->guard('contact')->loginUsingId($contact->id, true);
$this->dispatch('purchase.context', property: 'contact', value: $contact); // $this->dispatch('purchase.context', property: 'contact', value: $contact);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
return; return;
@ -162,7 +163,7 @@ class Login extends Component
if ($attempt) { if ($attempt) {
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user()); // $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }
@ -172,7 +173,7 @@ class Login extends Component
public function mount() public function mount()
{ {
if (auth()->guard('contact')->check()) { if (auth()->guard('contact')->check()) {
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user()); // $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }

View File

@ -92,7 +92,7 @@ class Register extends Component
auth()->guard('contact')->loginUsingId($contact->id, true); auth()->guard('contact')->loginUsingId($contact->id, true);
$this->dispatch('purchase.context', property: 'contact', value: $contact); // $this->dispatch('purchase.context', property: 'contact', value: $contact);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }
@ -112,7 +112,7 @@ class Register extends Component
auth()->guard('contact')->loginUsingId($contact->id, true); auth()->guard('contact')->loginUsingId($contact->id, true);
$this->dispatch('purchase.context', property: 'contact', value: $contact); // $this->dispatch('purchase.context', property: 'contact', value: $contact);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
return; return;
@ -161,7 +161,7 @@ class Register extends Component
public function mount() public function mount()
{ {
if (auth()->guard('contact')->check()) { if (auth()->guard('contact')->check()) {
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user()); // $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }

View File

@ -125,10 +125,10 @@ class RegisterOrLogin extends Component
$cc->email = $this->email; $cc->email = $this->email;
$nmo = new NinjaMailerObject(); $nmo = new NinjaMailerObject();
$nmo->mailable = new OtpCode($this->subscription()->company, $this->context['contact'] ?? null, $code); $nmo->mailable = new OtpCode($this->subscription()->company, $contact, $code);
$nmo->company = $this->subscription()->company; $nmo->company = $this->subscription()->company;
$nmo->settings = $this->subscription()->company->settings; $nmo->settings = $this->subscription()->company->settings;
$nmo->to_user = $cc; $nmo->to_user = $contact;
NinjaMailerJob::dispatch($nmo); NinjaMailerJob::dispatch($nmo);
@ -161,7 +161,7 @@ class RegisterOrLogin extends Component
if ($contact) { if ($contact) {
auth()->guard('contact')->loginUsingId($contact->id, true); auth()->guard('contact')->loginUsingId($contact->id, true);
$this->dispatch('purchase.context', property: 'contact', value: $contact); // $this->dispatch('purchase.context', property: 'contact', value: $contact);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
return; return;
@ -184,8 +184,6 @@ class RegisterOrLogin extends Component
additional: $this->additional_fields, additional: $this->additional_fields,
); );
nlog($data);
$rules = $service->rules(); $rules = $service->rules();
$data = Validator::make($data, $rules)->validate(); $data = Validator::make($data, $rules)->validate();
@ -194,7 +192,7 @@ class RegisterOrLogin extends Component
auth()->guard('contact')->loginUsingId($contact->id, true); auth()->guard('contact')->loginUsingId($contact->id, true);
$this->dispatch('purchase.context', property: 'contact', value: $contact); // $this->dispatch('purchase.context', property: 'contact', value: $contact);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
} }
@ -214,7 +212,7 @@ class RegisterOrLogin extends Component
auth()->guard('contact')->loginUsingId($contact->id, true); auth()->guard('contact')->loginUsingId($contact->id, true);
$this->dispatch('purchase.context', property: 'contact', value: $contact); // $this->dispatch('purchase.context', property: 'contact', value: $contact);
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
return; return;
@ -264,7 +262,7 @@ class RegisterOrLogin extends Component
{ {
if (auth()->guard('contact')->check()) { if (auth()->guard('contact')->check()) {
$this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user()); // $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user());
$this->dispatch('purchase.next'); $this->dispatch('purchase.next');
return; return;

View File

@ -27,6 +27,20 @@ class Coupon extends Component
public ?string $couponCode = null; public ?string $couponCode = null;
public bool $showCouponCode = false;
public function mount()
{
$subscription = $this->subscription();
$this->showCouponCode = ($subscription->promo_discount > 0) && (!array_key_exists('valid_coupon',$this->context));
if(isset($this->context['request_data']['coupon']) && $this->context['request_data']['coupon'] == $this->subscription()->promo_code){
$this->showCouponCode = false;
$this->dispatch('purchase.context', property: "valid_coupon", value: $this->context['request_data']['coupon']);
}
}
#[Computed()] #[Computed()]
public function subscription() public function subscription()
{ {
@ -35,6 +49,7 @@ class Coupon extends Component
public function applyCoupon() public function applyCoupon()
{ {
$this->validate([ $this->validate([
'couponCode' => ['required', 'string', 'min:3'], 'couponCode' => ['required', 'string', 'min:3'],
]); ]);
@ -42,25 +57,20 @@ class Coupon extends Component
try { try {
if($this->couponCode == $this->subscription()->promo_code) { if($this->couponCode == $this->subscription()->promo_code) {
$this->showCouponCode = false;
$this->dispatch('purchase.context', property: "valid_coupon", value: $this->couponCode);
$this->couponCode = null; $this->dispatch('summary.refresh');
} }
else { else {
$this->addError('couponCode', 'Invalid coupon code.'); $this->addError('couponCode', ctrans('texts.invalid_coupon'));
} }
} catch (\Exception $e) { } catch (\Exception $e) {
$this->addError('couponCode', 'Invalid coupon code.'); $this->addError('couponCode', ctrans('texts.invalid_coupon'));
}
} }
// public function quantity($id, $value): void
// { }
// $this->dispatch('purchase.context', property: "bundle.optional_one_time_products.{$id}.quantity", value: $value);
// }
public function render(): \Illuminate\View\View public function render(): \Illuminate\View\View
{ {

View File

@ -29,17 +29,12 @@ class Methods extends Component
public function mount(): void public function mount(): void
{ {
nlog($this->subscription_id);
$total = collect($this->context['products'])->sum('total_raw'); $total = collect($this->context['products'])->sum('total_raw');
$methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods($total); //@todo this breaks down when the cart is in front of the login - we have no context on the user - nor their country/currency() $methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods($total); //@todo this breaks down when the cart is in front of the login - we have no context on the user - nor their country/currency()
$this->methods = $methods; $this->methods = $methods;
nlog($methods);
} }
public function handleSelect(string $company_gateway_id, string $gateway_type_id) public function handleSelect(string $company_gateway_id, string $gateway_type_id)

View File

@ -82,63 +82,99 @@ class Summary extends Component
} }
$this->dispatch('purchase.context', property: 'bundle', value: $bundle); $this->dispatch('purchase.context', property: 'bundle', value: $bundle);
} }
public function oneTimePurchasesTotal(bool $raw = false) /**
* Base calculations for one-time purchases
*/
#[Computed]
public function oneTimePurchasesTotal(): float
{ {
if (isset($this->context['bundle']['recurring_products']) === false) { if (!isset($this->context['bundle']['one_time_products'])) {
return 0; return 0.0;
} }
$one_time = collect($this->context['bundle']['one_time_products'])->sum(function ($item) { $one_time = collect($this->context['bundle']['one_time_products'])->sum(function ($item) {
return $item['product']['price'] * $item['quantity']; return (float)$item['product']['price'] * (float)$item['quantity'];
}); });
$one_time_optional = collect($this->context['bundle']['optional_one_time_products'])->sum(function ($item) { $one_time_optional = collect($this->context['bundle']['optional_one_time_products'])->sum(function ($item) {
return $item['product']['price'] * $item['quantity']; return (float)$item['product']['price'] * (float)$item['quantity'];
}); });
if ($raw) { return (float)$one_time + (float)$one_time_optional;
return $one_time + $one_time_optional;
} }
return Number::formatMoney($one_time + $one_time_optional, $this->subscription()->company); /**
* Base calculations for recurring purchases
} */
#[Computed]
public function recurringPurchasesTotal(bool $raw = false) public function recurringPurchasesTotal(): float
{ {
if (isset($this->context['bundle']['recurring_products']) === false) { if (!isset($this->context['bundle']['recurring_products'])) {
return 0; return 0.0;
} }
$recurring = collect($this->context['bundle']['recurring_products'])->sum(function ($item) { $recurring = collect($this->context['bundle']['recurring_products'])->sum(function ($item) {
return $item['product']['price'] * $item['quantity']; return (float)$item['product']['price'] * (float)$item['quantity'];
}); });
$recurring_optional = collect($this->context['bundle']['optional_recurring_products'])->sum(function ($item) { $recurring_optional = collect($this->context['bundle']['optional_recurring_products'])->sum(function ($item) {
return $item['product']['price'] * $item['quantity']; return (float)$item['product']['price'] * (float)$item['quantity'];
}); });
if ($raw) { return (float)$recurring + (float)$recurring_optional;
return $recurring + $recurring_optional;
} }
return \sprintf( /**
'%s/%s', * Calculate subtotal before any discounts
Number::formatMoney($recurring + $recurring_optional, $this->subscription()->company), */
RecurringInvoice::frequencyForKey($this->subscription()->frequency_id ?? 0) #[Computed]
protected function calculateSubtotal(): float
{
return $this->oneTimePurchasesTotal() + $this->recurringPurchasesTotal();
}
/**
* Calculate discount amount based on subtotal
*/
#[Computed]
public function discount(): float
{
if (!isset($this->context['valid_coupon']) ||
$this->context['valid_coupon'] != $this->subscription()->promo_code) {
return 0.0;
}
$subscription = $this->subscription();
$discount = $subscription->promo_discount;
return $subscription->is_amount_discount
? $discount
: ($this->calculateSubtotal() * $discount/100);
}
/**
* Format subtotal for display
*/
#[Computed]
public function subtotal(): string
{
return Number::formatMoney(
$this->calculateSubtotal(),
$this->subscription()->company
); );
} }
#[Computed()] /**
public function total() * Calculate and format final total
*/
#[Computed]
public function total(): string
{ {
return Number::formatMoney( return Number::formatMoney(
collect([ $this->calculateSubtotal() - $this->discount(),
$this->oneTimePurchasesTotal(raw: true),
$this->recurringPurchasesTotal(raw: true),
])->sum(),
$this->subscription()->company $this->subscription()->company
); );
} }
@ -192,6 +228,23 @@ class Summary extends Component
return $products; return $products;
} }
#[On('summary.refresh')]
public function refresh()
{
// nlog("am i refreshing here?");
// $this->oneTimePurchasesTotal = $this->oneTimePurchasesTotal();
// $this->recurringPurchasesTotal = $this->recurringPurchasesTotal();
// $this->discount = $this->discount();
// nlog($this->oneTimePurchasesTotal);
// nlog($this->recurringPurchasesTotal);
// nlog($this->discount);
}
public function render() public function render()
{ {
return view('billing-portal.v3.summary'); return view('billing-portal.v3.summary');

View File

@ -214,10 +214,14 @@ class Subscription extends BaseModel
$in_stock_quantity = data_get($product, 'in_stock_quantity', 0); $in_stock_quantity = data_get($product, 'in_stock_quantity', 0);
$max_limit = 100; $max_limit = 100;
if(!$this->use_inventory_management) if (!$this->use_inventory_management) {
return $max_quantity != 0 ? $max_quantity : $max_limit; return min($max_limit, $max_quantity > 0 ? $max_quantity : $max_limit);
}
return $max_quantity !=0 ? $max_quantity : min($max_limit, $in_stock_quantity); if ($max_quantity > 0) {
return min($max_limit, $max_quantity);
}
return min($max_limit, $in_stock_quantity);
} }
} }

View File

@ -229,7 +229,6 @@ class UpdatePaymentMethods
private function buildPaymentMethodMeta(PaymentMethod $method, $type_id) private function buildPaymentMethodMeta(PaymentMethod $method, $type_id)
{ {
nlog($method->type);
switch ($type_id) { switch ($type_id) {
case GatewayType::CREDIT_CARD: case GatewayType::CREDIT_CARD:

View File

@ -14,6 +14,7 @@
@endif @endif
<livewire:billing-portal.cart.optional-recurring-products <livewire:billing-portal.cart.optional-recurring-products
:subscription_id="$this->subscription->hashed_id"
:context="$context" :context="$context"
/> />
@ -24,12 +25,10 @@
:context="$context" :context="$context"
/> />
@if($this->subscription->promo_discount > 0)
<livewire:billing-portal.cart.coupon <livewire:billing-portal.cart.coupon
:subscription_id="$this->subscription->hashed_id" :subscription_id="$this->subscription->hashed_id"
:context="$context" :context="$context"
/> />
@endif
<div class="mt-3"> <div class="mt-3">
<form wire:submit="handleSubmit"> <form wire:submit="handleSubmit">

View File

@ -1,11 +1,12 @@
<div class="space-y-10"> <div class="space-y-10">
@if($showCouponCode)
<div> <div>
<div class="flex rounded-lg overflow-hidden border border-gray-300"> <div class="flex rounded-lg overflow-hidden border border-gray-300">
<div class="relative flex-grow"> <div class="relative flex-grow">
<input <input
type="text" type="text"
wire:model.live="couponCode" wire:model="couponCode"
placeholder="Enter coupon code" placeholder="{{ __('texts.promo_code') }}"
class="block w-full px-4 py-2 border-0 outline-none focus:ring-0 sm:text-sm" class="block w-full px-4 py-2 border-0 outline-none focus:ring-0 sm:text-sm"
> >
</div> </div>
@ -14,7 +15,7 @@
wire:loading.attr="disabled" wire:loading.attr="disabled"
class="inline-flex items-center border-l border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primary-500" class="inline-flex items-center border-l border-gray-300 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primary-500"
> >
<span wire:loading.remove wire:target="applyCoupon">Apply</span> <span wire:loading.remove wire:target="applyCoupon">{{ __('texts.apply') }}</span>
<span wire:loading wire:target="applyCoupon"> <span wire:loading wire:target="applyCoupon">
<svg class="h-4 w-4 animate-spin" viewBox="0 0 24 24"> <svg class="h-4 w-4 animate-spin" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"/> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"/>
@ -27,4 +28,5 @@
<p class="mt-2 text-sm text-red-600">{{ $message }}</p> <p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror @enderror
</div> </div>
@endif
</div> </div>

View File

@ -29,15 +29,15 @@
<div class="flex flex-col-reverse space-y-3"> <div class="flex flex-col-reverse space-y-3">
<div class="flex"> <div class="flex">
@if($subscription->use_inventory_management && $product['in_stock_quantity'] <= 0) @if($this->subscription->use_inventory_management && $product['in_stock_quantity'] <= 0)
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p> <p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
@else @else
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p> <p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
@endif @endif
<select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}> <select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}>
<option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option> <option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option>
@for ($i = 1; $i <= $subscription->maxQuantity($product); $i++) @for ($i = 1; $i <= $this->subscription->maxQuantity($product); $i++)
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option> <option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
@endfor @endfor
</select> </select>

View File

@ -23,22 +23,22 @@
<div class="flex flex-col"> <div class="flex flex-col">
<h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2> <h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2>
<p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($subscription->frequency_id) }}</span></p> <p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($this->subscription->frequency_id) }}</span></p>
</div> </div>
</div> </div>
<div class="flex flex-col-reverse space-y-3"> <div class="flex flex-col-reverse space-y-3">
<div class="flex"> <div class="flex">
@if($subscription->use_inventory_management && $product['in_stock_quantity'] <= 0) @if($this->subscription->use_inventory_management && $product['in_stock_quantity'] <= 0)
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p> <p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
@else @else
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p> <p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
@endif @endif
<select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}> <select id="{{ $product['hashed_id'] }}" wire:change="quantity($event.target.id, $event.target.value)" class="rounded-md border-gray-300 shadow-sm sm:text-sm" {{ $this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}>
<option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option> <option {{ $entry['quantity'] == '0' ? 'selected' : '' }} value="0" selected="selected">0</option>
@for ($i = 1; $i <= $subscription->maxQuantity($product); $i++) @for ($i = 1; $i <= $this->subscription->maxQuantity($product); $i++)
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option> <option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
@endfor @endfor
</select> </select>

View File

@ -23,14 +23,14 @@
<div class="flex flex-col"> <div class="flex flex-col">
<h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2> <h2 class="text-lg font-medium">{{ $product['product_key'] }}</h2>
<p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($subscription->frequency_id) }}</span></p> <p class="block text-sm">{{ \App\Utils\Number::formatMoney($product['price'], $this->subscription['company']) }} / <span class="lowercase">{{ App\Models\RecurringInvoice::frequencyForKey($this->subscription->frequency_id) }}</span></p>
</div> </div>
</div> </div>
<div class="flex flex-col-reverse space-y-3"> <div class="flex flex-col-reverse space-y-3">
<div class="flex"> <div class="flex">
@if($subscription->per_seat_enabled) @if($this->subscription->per_seat_enabled)
@if($subscription->use_inventory_management && $product['in_stock_quantity'] < 1) @if($this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1)
<p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p> <p class="text-sm font-light text-red-500 text-right mr-2 mt-2">{{ ctrans('texts.out_of_stock') }}</p>
@else @else
<p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p> <p class="text-sm font-light text-gray-700 text-right mr-2 mt-2">{{ ctrans('texts.qty') }}</p>
@ -40,19 +40,13 @@
id="{{ $product['hashed_id'] }}" id="{{ $product['hashed_id'] }}"
class="rounded-md border-gray-300 shadow-sm sm:text-sm" class="rounded-md border-gray-300 shadow-sm sm:text-sm"
wire:change="quantity($event.target.id, $event.target.value)" wire:change="quantity($event.target.id, $event.target.value)"
{{ $subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }} {{ $this->subscription->use_inventory_management && $product['in_stock_quantity'] < 1 ? 'disabled' : '' }}
> >
<option {{ $entry['quantity'] == '1' ? 'selected' : '' }} value="1">1</option> <option {{ $entry['quantity'] == '1' ? 'selected' : '' }} value="1">1</option>
@if($subscription->max_seats_limit > 1) @for ($i = 1; $i <= $this->subscription->maxQuantity($product); $i++)
@for ($i = 2; $i <= ($subscription->use_inventory_management ? min($this->subscription->max_seats_limit,$product['in_stock_quantity']) : $subscription->max_seats_limit); $i++)
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option> <option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
@endfor @endfor
@else
@for ($i = 2; $i <= ($subscription->use_inventory_management ? min($product['in_stock_quantity'], min(100,$product['max_quantity'])) : min(100,$product['max_quantity'])); $i++)
<option {{ $entry['quantity'] == $i ? 'selected' : '' }} value="{{ $i }}">{{ $i }}</option>
@endfor
@endif
</select> </select>
@endif @endif
</div> </div>

View File

@ -16,17 +16,27 @@
<div class="space-y-2 mt-4 border-t pt-2"> <div class="space-y-2 mt-4 border-t pt-2">
<div class="flex justify-between text-sm"> <div class="flex justify-between text-sm">
<span class="uppercase">{{ ctrans('texts.one_time_purchases') }}</span> <span class="uppercase">{{ ctrans('texts.one_time_purchases') }}</span>
<span>{{ $this->oneTimePurchasesTotal() }}</span> <span>{{ \App\Utils\Number::formatMoney($this->oneTimePurchasesTotal(), $this->subscription->company) }}</span>
</div> </div>
<div class="flex justify-between text-sm"> <div class="flex justify-between text-sm">
<span class="uppercase">{{ ctrans('texts.recurring_purchases') }}</span> <span class="uppercase">{{ ctrans('texts.recurring_purchases') }}</span>
<span>{{ $this->recurringPurchasesTotal() }}</span> <span>{{ \App\Utils\Number::formatMoney($this->recurringPurchasesTotal(), $this->subscription->company) }}</span>
</div> </div>
<div <div class="flex justify-between text-sm uppercase border-t pt-2">
class="flex justify-between text-sm uppercase border-t pt-2" <span>{{ ctrans('texts.subtotal') }}</span>
> <span>{{ $this->subtotal() }}</span>
</div>
@if($this->discount() > 0)
<div class="flex justify-between text-sm uppercase">
<span>{{ ctrans('texts.discount') }}</span>
<span class="font-semibold">{{ \App\Utils\Number::formatMoney($this->discount(), $this->subscription->company) }}</span>
</div>
@endif
<div class="flex justify-between text-sm uppercase border-t pt-2">
<span>{{ ctrans('texts.total') }}</span> <span>{{ ctrans('texts.total') }}</span>
<span class="font-semibold">{{ $this->total() }}</span> <span class="font-semibold">{{ $this->total() }}</span>
</div> </div>