@extends('layouts.dashboard') @section('content') @php /** * Vendor subscription billing. * * The restaurant's whole billing record in one place: the plan it is on and how long the term * has left, what the plan allows against what is being used, every payment it has made with a * printable invoice for each, the pay/renew panel, and the path to a different plan. * * @var array|null $plan current plan row (or null) * @var array|null $subscription latest subscription row (or null) * @var array $history this page of the restaurant's subscription payments, newest first * @var array $pager pagination metadata for $history * @var array $term ['state','ends_at','days_left','lifetime'] — how the current term stands * @var array $allowance menu-item allowance and usage for the current plan * @var array $planOptions active plans other than the current one * @var bool $canPayByGateway true when Stripe or PayPal is enabled and keyed * @var float $price plan price * @var bool $isFree true when price <= 0 * @var string $currency ISO currency code * @var array $methods ['offline'=>bool,'stripe'=>bool,'paypal'=>bool] * @var string $offlineInstructions admin-configured offline payment text */ $cycleLabel = [ 'monthly' => t_raw('vendor.billing.cycle_monthly_suffix'), 'yearly' => t_raw('vendor.billing.cycle_yearly_suffix'), 'lifetime' => t_raw('vendor.billing.cycle_lifetime_suffix'), ]; $statusPill = [ 'active' => 'qm-pill-green', 'pending' => 'qm-pill-amber', 'expired' => 'qm-pill-grey', 'cancelled' => 'qm-pill-grey', ]; $subStatus = $subscription['status'] ?? ''; $canPay = !$isFree && ($methods['offline'] || $methods['stripe'] || $methods['paypal']); $daysLeft = (int) $term['days_left']; @endphp

{!! t('vendor.billing.your_plan_title') !!}

@if ($subStatus !== '') {!! status_label('subscription', (string) $subStatus) !!} @endif
@php /* Renewal and expiry are stated up front, in days, so "when do I need to act?" never requires reading a date out of a table and doing the arithmetic. */ @endphp @if ($term['state'] === 'lapsed')
{!! t('vendor.billing.lapsed_title') !!}

{!! t('vendor.billing.lapsed_text', [':date' => fmt_day($term['ends_at'], true), ':days' => number_format(abs($daysLeft))]) !!}

@elseif ($term['state'] === 'ended')
{!! t('vendor.billing.ended_title', [':status' => status_label('subscription', (string) $subStatus)]) !!}

{!! t('vendor.billing.ended_text') !!}

@elseif ($term['state'] === 'expiring')
{!! t('vendor.billing.expiring_title', [':days' => number_format($daysLeft)]) !!}

{!! t('vendor.billing.expiring_text', [':date' => fmt_day($term['ends_at'], true)]) !!}

@endif @if ($plan)
{{ (string) $plan['name'] }} @if ($isFree){!! t('common.free') !!}@else{!! money($price) !!} {{ $cycleLabel[$plan['billing_cycle']] ?? '' }}@endif
{!! t('common.status') !!}
{!! $subscription ? '' . status_label('subscription', (string) $subStatus) . '' : t('vendor.billing.no_active_sub') !!}
{!! t('vendor.billing.renews_ends_label') !!}
@if ($term['lifetime']) {!! t('vendor.billing.never_lifetime') !!} @elseif ($term['ends_at'] !== null) {!! fmt_day($term['ends_at']) !!} @if ($term['state'] === 'active' || $term['state'] === 'expiring') {!! t('vendor.billing.days_left', [':days' => number_format($daysLeft)]) !!} @endif @else {!! dash() !!} @endif
{!! t('vendor.billing.commission_label') !!}
{{ (string) (float) $plan['commission_percent'] }}%{!! t('vendor.billing.commission_hint') !!}
{!! t('vendor.billing.allowance_label') !!}
@if ($allowance['unlimited']) {!! t('vendor.billing.allowance_unlimited', [':used' => number_format($allowance['used'])]) !!} @else {!! t('vendor.billing.allowance_used', [':used' => number_format($allowance['used']), ':limit' => number_format($allowance['limit'])]) !!} {!! $allowance['reached'] ? t('vendor.billing.allowance_full') : t('vendor.billing.allowance_remaining', [':n' => number_format($allowance['remaining'])]) !!} @endif
@if ($subscription && !empty($subscription['payment_method']))
{!! t('vendor.billing.last_payment_label') !!}
{!! status_label('payment_method', (string) $subscription['payment_method']) !!}
@endif
@else

{!! t('vendor.billing.no_plan_text') !!}

@endif
@if ($plan && $isFree)

{!! t('vendor.billing.free_plan_title') !!}

{!! t('vendor.billing.free_plan_text', [':site' => setting('site_name', 'QuickMunch')]) !!}

@elseif ($plan)

{!! t('vendor.billing.pay_renew_title') !!}

{!! t('vendor.billing.pay_renew_sub', [':plan' => (string) $plan['name'], ':price' => money($price), ':currency' => $currency]) !!}

@if (!$canPay)

{!! t('vendor.billing.no_method_title') !!}

{!! t('vendor.billing.no_method_text') !!}

@else
@if ($methods['offline'])
{!! t('status.payment_method.offline') !!}

{!! t('vendor.billing.offline_payment_note') !!}

@if (trim($offlineInstructions) !== '')

{!! t('vendor.billing.how_to_pay_label') !!}
{!! nl2br(e(trim($offlineInstructions))) !!}

@endif
@endif @if ($methods['stripe'])
{!! t('vendor.billing.card_stripe_label') !!}

{!! t('vendor.billing.stripe_note') !!}

{!! csrf_field() !!}
@endif @if ($methods['paypal'])
{!! t('status.payment_method.paypal') !!}

{!! t('vendor.billing.paypal_note') !!}

{!! csrf_field() !!}
@endif
@endif
@endif @if ($plan && $planOptions)

{!! t('vendor.billing.change_plan_title') !!}

@php /* What actually happens is stated plainly rather than implied: this build does not prorate, so an unfinished term is forfeited and the copy has to say so. */ @endphp

{!! t('vendor.billing.change_plan_sub') !!}

@foreach ($planOptions as $option) @php $optionPrice = (float) $option['price']; $optionFree = $optionPrice <= 0; $isUpgrade = $optionPrice > $price; // A paid plan needs a gateway to buy it; a free plan needs nothing, because there is // no money to take. Offline payment stays administrator-only by design. $selectable = $optionFree || $canPayByGateway; @endphp
{{ (string) $option['name'] }} {!! $isUpgrade ? t('vendor.billing.upgrade_pill') : t('vendor.billing.downgrade_pill') !!}

{!! $optionFree ? t('common.free') : money($optionPrice) !!} @if (!$optionFree){{ $cycleLabel[$option['billing_cycle']] ?? '' }}@endif

{!! t('vendor.billing.change_plan_terms', [ ':commission' => (string) (float) $option['commission_percent'], ':items' => (int) $option['max_menu_items'] > 0 ? number_format((int) $option['max_menu_items']) : t_raw('admin.plans.unlimited'), ]) !!}

@if ($term['lifetime'] || $term['ends_at'] === null || $daysLeft <= 0) {!! t('vendor.billing.change_plan_no_term_left') !!} @else {!! t('vendor.billing.change_plan_forfeit', [':days' => number_format($daysLeft), ':plan' => (string) $plan['name']]) !!} @endif

@if ($selectable)
{!! csrf_field() !!} @if (!$optionFree)
@endif
@else

{!! t('vendor.billing.change_plan_contact_admin') !!}

@endif
@endforeach
@endif

{!! t('vendor.billing.history_title') !!}

{!! t('vendor.billing.history_sub') !!}

@php /* Period is a date range (two values), not one Date.parse-able cell, so that carries no data-sort. */ @endphp @if ($history) @foreach ($history as $row) @php $rowStatus = (string) $row['status']; @endphp @endforeach @else @include('partials.table-empty', ['colspan' => 7, 'icon' => 'fa-file-invoice-dollar', 'msg' => t_raw('vendor.billing.history_empty')]) @endif
{!! t('vendor.billing.history_title') !!}
{!! t('common.date') !!} {!! t('admin.subscriptions.col_plan') !!} {!! t('common.period') !!} {!! t('common.amount') !!} {!! t('vendor.billing.col_method') !!} {!! t('common.status') !!} {!! t('common.actions') !!}
{!! fmt_day($row['created_at']) !!} {!! $row['plan_name'] !== '' ? plan_tag((string) $row['plan_slug'], (string) $row['plan_name']) : dash() !!} @if (!empty($row['starts_at'])) {!! fmt_day($row['starts_at']) !!} – {!! !empty($row['ends_at']) ? fmt_day($row['ends_at']) : t('vendor.billing.never_lifetime') !!} @else {!! dash() !!} @endif {!! money($row['amount_paid']) !!} {!! !empty($row['payment_method']) ? status_label('payment_method', (string) $row['payment_method']) : dash() !!} {!! status_label('subscription', $rowStatus) !!} @php /* A checkout that was started but never captured has no money behind it, so there is nothing to invoice. */ @endphp @include('partials.row-actions', ['inline' => 1, 'actions' => [ $rowStatus !== 'pending' ? [ 'label' => t_raw('vendor.billing.view_invoice'), 'icon' => 'fa-file-invoice', 'href' => '/vendor/billing/invoice/' . (int) $row['id'], 'primary' => true, ] : null, ]])
@include('partials.table-toolbar', ['pager' => $pager, 'base' => '/vendor/billing'])
@endsection