diff --git a/app/Http/Controllers/Events/ProController.php b/app/Http/Controllers/Events/ProController.php index 85086ad..e67a966 100644 --- a/app/Http/Controllers/Events/ProController.php +++ b/app/Http/Controllers/Events/ProController.php @@ -3,134 +3,52 @@ namespace App\Http\Controllers\Events; use App\Http\Controllers\Controller; -use App\Models\Events\ProSubscription; -use App\Models\User; use App\Services\Billing\BillingClient; use App\Services\Events\SubscriptionService; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; -use Illuminate\View\View; +/** + * Paid Events plans are retired. Routes remain so old bookmarks and emails + * do not 404; every action redirects to the dashboard. + */ class ProController extends Controller { public function __construct(private readonly SubscriptionService $subscriptions) {} - public function index(Request $request): View + public function index(Request $request): RedirectResponse { - $user = ladill_account() ?? $request->user(); - $planKey = $this->subscriptions->planKey($user); - - return view('events.pro.index', [ - 'subscription' => $this->subscriptions->subscriptionFor($user), - 'planKey' => $planKey, - 'isPro' => $planKey === ProSubscription::PLAN_PRO, - 'isEnterprise' => $planKey === ProSubscription::PLAN_ENTERPRISE, - 'hasPaidPlan' => $this->subscriptions->hasPaidPlan($user), - 'gatingActive' => $this->subscriptions->gatingActive(), - 'proPriceMinor' => $this->subscriptions->priceMinor(), - 'enterprisePriceMinor' => $this->subscriptions->enterprisePriceMinor(), - 'prepaidMonths' => (array) config('events.prepaid_months', [6, 12, 24]), - 'currency' => (string) config('events.pro.currency', 'GHS'), - ]); + return $this->retired(); } public function subscribe(Request $request): RedirectResponse { - [$ok, $message] = $this->subscriptions->subscribe(ladill_account() ?? $request->user()); - - return redirect()->route('events.pro.index')->with($ok ? 'success' : 'error', $message); + return $this->retired(); } public function subscribeEnterprise(Request $request): RedirectResponse { - [$ok, $message] = $this->subscriptions->subscribeEnterprise(ladill_account() ?? $request->user()); - - return redirect()->route('events.pro.index')->with($ok ? 'success' : 'error', $message); + return $this->retired(); } public function subscribePrepaid(Request $request, BillingClient $billing): RedirectResponse { - $validated = $request->validate([ - 'plan' => ['required', 'in:pro,enterprise'], - 'months' => ['required', 'integer', 'in:6,12,24'], - ]); - - $user = ladill_account() ?? $request->user(); - if ($this->subscriptions->hasPaidPlan($user)) { - return redirect()->route('events.pro.index') - ->with('success', 'You already have an active subscription.'); - } - - $plan = $validated['plan']; - $months = (int) $validated['months']; - $monthlyMinor = $plan === 'enterprise' - ? $this->subscriptions->enterprisePriceMinor() - : $this->subscriptions->priceMinor(); - - try { - $checkout = $billing->initiatePlanCheckout( - $user, - $plan, - $months, - $monthlyMinor * $months, - route('events.pro.paystack.callback'), - ['user_id' => $user->id], - ); - } catch (\Throwable) { - return redirect()->route('events.pro.index') - ->with('error', 'Could not start Paystack checkout. Please try again.'); - } - - $url = trim((string) ($checkout['checkout_url'] ?? '')); - if ($url === '') { - return redirect()->route('events.pro.index') - ->with('error', 'Paystack did not return a checkout URL.'); - } - - return redirect()->away($url); + return $this->retired(); } public function paystackCallback(Request $request, BillingClient $billing): RedirectResponse { - $reference = (string) $request->query('reference', ''); - if ($reference === '') { - return redirect()->route('events.pro.index')->with('error', 'Missing payment reference.'); - } - - try { - $result = $billing->verifyPlanCheckout($reference); - } catch (\Throwable) { - return redirect()->route('events.pro.index') - ->with('error', 'Could not verify payment. Contact support with reference: '.$reference); - } - - if (! ($result['paid'] ?? false)) { - return redirect()->route('events.pro.index') - ->with('error', 'Payment was not completed.'); - } - - $metadata = (array) ($result['metadata'] ?? []); - $user = User::query()->find((int) ($metadata['user_id'] ?? 0)); - $account = ladill_account() ?? $request->user(); - if (! $user || ! $account || $user->id !== $account->id) { - return redirect()->route('events.pro.index') - ->with('error', 'Account not found for this payment.'); - } - - $plan = (string) ($result['plan'] ?? 'pro'); - $months = (int) ($result['months'] ?? 0); - $this->subscriptions->activatePrepaid($user, $plan, $months); - - $label = $plan === 'enterprise' ? 'Events Business' : 'Events Pro'; - - return redirect()->route('events.pro.index') - ->with('success', "{$label} is active for {$months} months."); + return $this->retired(); } public function cancel(Request $request): RedirectResponse { - [$ok, $message] = $this->subscriptions->cancel(ladill_account() ?? $request->user()); + return $this->retired(); + } - return redirect()->route('events.pro.index')->with($ok ? 'success' : 'error', $message); + private function retired(): RedirectResponse + { + return redirect()->route('events.dashboard') + ->with('success', 'Ladill Events is free — paid subscriptions are no longer offered. Ticket payments use Ladill Pay with the standard platform fee.'); } } diff --git a/app/Http/Middleware/EnsurePro.php b/app/Http/Middleware/EnsurePro.php index 1016a17..befb8fa 100644 --- a/app/Http/Middleware/EnsurePro.php +++ b/app/Http/Middleware/EnsurePro.php @@ -13,12 +13,7 @@ class EnsurePro public function handle(Request $request, Closure $next): Response { - $user = ladill_account() ?? $request->user(); - if ($user && $this->subscriptions->isPro($user)) { - return $next($request); - } - - return redirect()->route('events.pro.index') - ->with('upsell', 'This feature is part of Ladill Events Pro or Business.'); + // Paid Events plans are retired — all authenticated users have full access. + return $next($request); } } diff --git a/app/Services/Events/SubscriptionService.php b/app/Services/Events/SubscriptionService.php index 069cd35..f1e90d4 100644 --- a/app/Services/Events/SubscriptionService.php +++ b/app/Services/Events/SubscriptionService.php @@ -17,7 +17,8 @@ class SubscriptionService public function gatingActive(): bool { - return (bool) config('events.pro.enabled', true) && $this->billing->configured(); + // Paid Events subscriptions are retired — product is free for all accounts. + return false; } public function priceMinor(): int @@ -74,10 +75,10 @@ class SubscriptionService return $this->hasPaidPlan($user); } - /** Own payment gateway (Paystack / Flutterwave / Hubtel) requires Pro or Business. */ + /** Custom / owner payment gateways are retired — Ladill Pay only. */ public function canUsePaymentGateway(User $user): bool { - return $this->hasPaidPlan($user); + return false; } public function liveEventCount(User $user): int diff --git a/app/Services/Payments/MerchantGatewayService.php b/app/Services/Payments/MerchantGatewayService.php index 38633bc..1bf520b 100644 --- a/app/Services/Payments/MerchantGatewayService.php +++ b/app/Services/Payments/MerchantGatewayService.php @@ -24,8 +24,9 @@ class MerchantGatewayService public function shouldUseOwnerGateway(User|string $owner): bool { - return $this->ownerMayUseGateway($owner) - && (bool) $this->settingFor($owner)?->isConfigured(); + // Custom / owner payment gateways are retired. All checkouts use Ladill Pay + // with platform fees. + return false; } /** @@ -88,15 +89,7 @@ class MerchantGatewayService protected function ownerMayUseGateway(User|string $owner): bool { - $user = $owner instanceof User - ? $owner - : User::query()->where('public_id', (string) $owner)->first(); - - if (! $user) { - return false; - } - - return app(SubscriptionService::class)->canUsePaymentGateway($user); + return false; } /** diff --git a/config/events.php b/config/events.php index c7d2449..05bee3a 100644 --- a/config/events.php +++ b/config/events.php @@ -8,30 +8,27 @@ return [ 'meet_app_url' => env('LADILL_MEET_APP_URL', 'https://meet.ladill.com'), + /* + | Paid Events subscriptions (Pro / Business) are retired. Keep pro.* keys for + | legacy renew command / DB rows; gating is always off via SubscriptionService. + */ 'pro' => [ - 'enabled' => filter_var(env('EVENTS_PRO_ENABLED', true), FILTER_VALIDATE_BOOLEAN), + 'enabled' => false, 'price_minor' => (int) env('EVENTS_PRO_PRICE_MINOR', 49000), 'currency' => env('EVENTS_PRO_CURRENCY', 'GHS'), 'period_days' => (int) env('EVENTS_PRO_PERIOD_DAYS', 30), 'grace_days' => (int) env('EVENTS_PRO_GRACE_DAYS', 3), ], - 'plans' => [ - 'pro' => ['price_minor' => (int) env('EVENTS_PRO_PRICE_MINOR', 49000)], - 'enterprise' => ['price_minor' => (int) env('EVENTS_ENTERPRISE_PRICE_MINOR', 149000)], - ], + 'plans' => [], - 'prepaid_months' => [6, 12, 24], + 'prepaid_months' => [], 'free' => [ 'max_live_events' => (int) env('EVENTS_FREE_MAX_LIVE_EVENTS', 2), 'max_tickets_per_month' => (int) env('EVENTS_FREE_MAX_TICKETS_PER_MONTH', 100), ], - 'upgrade_banner' => [ - 'title' => 'Unlock Events Pro or Business', - 'description' => 'Unlimited events & tickets, with your own payment gateway — from GHS 490/mo.', - 'route' => 'events.pro.index', - ], + 'upgrade_banner' => null, ]; diff --git a/resources/views/events/payouts.blade.php b/resources/views/events/payouts.blade.php index c58681a..dfc5518 100644 --- a/resources/views/events/payouts.blade.php +++ b/resources/views/events/payouts.blade.php @@ -16,7 +16,7 @@

Payments & Payouts

-

Paid tickets and contributions settle directly to your connected gateway (0% Ladill fee). This wallet is for app subscriptions and older balances only.

+

Paid tickets and contributions settle via Ladill Pay (standard platform fee). Net proceeds land in your Ladill wallet for withdrawal.

@@ -97,7 +97,7 @@

Event payments

-

Legacy wallet credits from before BYO gateway settlement. New ticket revenue does not land here.

+

Ticket and contribution net proceeds after the Ladill Pay platform fee.

@if($transactions->isEmpty()) diff --git a/resources/views/events/pro/index.blade.php b/resources/views/events/pro/index.blade.php index 74cd148..20bf93c 100644 --- a/resources/views/events/pro/index.blade.php +++ b/resources/views/events/pro/index.blade.php @@ -36,7 +36,7 @@
- {{ $isEnterprise ? 'Business' : 'Pro' }} active + Business active @if ($subscription->current_period_end) until {{ $subscription->current_period_end->format('d M Y') }} @endif @@ -52,7 +52,7 @@ @elseif ($subscription->status === 'canceled') -
+ @csrf
@@ -61,7 +61,7 @@
@endif -
+

Free

GHS 0

@@ -69,54 +69,25 @@
  • {{ (int) config('events.free.max_live_events', 2) }} live events
  • {{ (int) config('events.free.max_tickets_per_month', 100) }} tickets / month
  • -
  • Your own Paystack / Flutterwave / Hubtel
  • -
  • 0% Ladill platform fee
  • +
  • Ladill Pay (zero-config)
  • +
  • 100 emails + 50 SMS / month
@if ($planKey === 'free')

Current plan

@endif
-
-

Pro

- -
    -
  • Unlimited events
  • -
  • Unlimited tickets
  • -
  • BYO payment gateway
  • -
  • Priority support
  • -
-
- @if ($planKey === 'pro') -

Current plan

- @elseif ($gatingActive && ! $hasPaidPlan) -
- @csrf - -
- @foreach ($prepaidMonths as $months) -
- @csrf - - - -
- @endforeach - @endif -
-
- -
+

Business

    -
  • Everything in Pro
  • -
  • Team seats
  • -
  • Advanced attendee tools
  • -
  • Dedicated onboarding
  • +
  • Unlimited events & tickets
  • +
  • Programmes & badges
  • +
  • Unlimited email & SMS
  • +
  • Team seats & dedicated onboarding
- @if ($planKey === 'enterprise') + @if (in_array($planKey, ['enterprise', 'pro'], true))

Current plan

@elseif ($gatingActive && ! $hasPaidPlan)
diff --git a/resources/views/partials/sidebar.blade.php b/resources/views/partials/sidebar.blade.php index fd2c67a..5336ef1 100644 --- a/resources/views/partials/sidebar.blade.php +++ b/resources/views/partials/sidebar.blade.php @@ -40,17 +40,5 @@ Settings - @php $proActive = request()->routeIs('events.pro.*'); @endphp - @if (! empty($hasPaidPlan)) - - - {{ ! empty($isEnterprise) ? 'Events Business' : 'Events Pro' }} - - @else - - - Upgrade to Pro - - @endif
diff --git a/resources/views/qr/account/settings.blade.php b/resources/views/qr/account/settings.blade.php index ce327e0..dc7ae68 100644 --- a/resources/views/qr/account/settings.blade.php +++ b/resources/views/qr/account/settings.blade.php @@ -272,31 +272,9 @@

Online payments

-

Ladill Pay is the recommended default and needs no API keys. Pro and Business may optionally select an owner gateway.

+

All ticket and contribution checkouts use Ladill Pay — zero-config, no owner API keys.

-

Ladill Pay is active on all plans and remains the automatic fallback.

- @if ($canUsePaymentGateway ?? false) - -
- - -
- - -

Incomplete or invalid credentials automatically fall back to Ladill Pay.

- @else -

Free uses Ladill Pay only. Upgrade to Pro to optionally connect your own gateway.

- @endif +

Ladill Pay is the only payment option. Standard platform fees apply on paid tickets and contributions and settle to your Ladill wallet.