153 lines
5.6 KiB
PHP
Executable File
153 lines
5.6 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\SuperAdmin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Invoice;
|
|
use App\Models\SubscriptionPlan;
|
|
use App\Models\User;
|
|
use App\Models\UserNotification;
|
|
use App\Models\UserSubscription;
|
|
use Barryvdh\DomPDF\Facade\Pdf;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\View\View;
|
|
|
|
class BillingController extends Controller
|
|
{
|
|
public function index(): View
|
|
{
|
|
$stats = [
|
|
'total_plans' => SubscriptionPlan::count(),
|
|
'active_plans' => SubscriptionPlan::where('is_active', true)->count(),
|
|
'active_subscriptions' => UserSubscription::where('status', 'active')->count(),
|
|
'total_revenue' => Invoice::where('status', 'paid')->sum('amount'),
|
|
'pending_invoices' => Invoice::where('status', 'pending')->count(),
|
|
'expiring_soon' => UserSubscription::where('status', 'active')
|
|
->where('end_date', '<=', now()->addDays(7))
|
|
->count(),
|
|
];
|
|
|
|
$plans = SubscriptionPlan::withCount('userSubscriptions')->get();
|
|
$subscriptions = UserSubscription::with(['user', 'plan'])
|
|
->orderByDesc('created_at')
|
|
->paginate(20);
|
|
|
|
return view('superadmin.billing.index', compact('stats', 'plans', 'subscriptions'));
|
|
}
|
|
|
|
public function storePlan(Request $request): RedirectResponse
|
|
{
|
|
$validated = $request->validate([
|
|
'name' => ['required', 'string', 'max:255'],
|
|
'description' => ['nullable', 'string'],
|
|
'price' => ['required', 'numeric', 'min:0'],
|
|
'currency' => ['required', 'string', 'size:3'],
|
|
'duration_days' => ['required', 'integer', 'min:1'],
|
|
'token_limit' => ['nullable', 'integer', 'min:0'],
|
|
]);
|
|
|
|
SubscriptionPlan::create($validated + ['is_active' => true]);
|
|
|
|
return back()->with('success', __('Plan created successfully.'));
|
|
}
|
|
|
|
public function updatePlan(Request $request, SubscriptionPlan $plan): RedirectResponse
|
|
{
|
|
$validated = $request->validate([
|
|
'name' => ['required', 'string', 'max:255'],
|
|
'description' => ['nullable', 'string'],
|
|
'price' => ['required', 'numeric', 'min:0'],
|
|
'currency' => ['required', 'string', 'size:3'],
|
|
'duration_days' => ['required', 'integer', 'min:1'],
|
|
'token_limit' => ['nullable', 'integer', 'min:0'],
|
|
'is_active' => ['boolean'],
|
|
]);
|
|
|
|
$plan->update($validated);
|
|
|
|
return back()->with('success', __('Plan updated successfully.'));
|
|
}
|
|
|
|
public function approvePayment(UserSubscription $subscription): RedirectResponse
|
|
{
|
|
$subscription->update(['payment_approved' => true, 'status' => 'active']);
|
|
|
|
// Create invoice
|
|
$lastInvoice = Invoice::orderByDesc('id')->first();
|
|
$nextNumber = $lastInvoice ? (int)filter_var($lastInvoice->invoice_number, FILTER_SANITIZE_NUMBER_INT) + 1 : 1001;
|
|
|
|
$invoice = Invoice::create([
|
|
'user_id' => $subscription->user_id,
|
|
'user_subscription_id' => $subscription->id,
|
|
'invoice_number' => 'INV-' . $nextNumber . '/' . now()->year,
|
|
'amount' => $subscription->plan->price,
|
|
'currency' => $subscription->plan->currency,
|
|
'status' => 'paid',
|
|
'payment_method' => 'manual',
|
|
'paid_at' => now(),
|
|
]);
|
|
|
|
// Generate PDF
|
|
$this->generateInvoicePdf($invoice);
|
|
|
|
// Notify user
|
|
UserNotification::create([
|
|
'user_id' => $subscription->user_id,
|
|
'type' => 'payment_received',
|
|
'title' => __('Payment Approved'),
|
|
'message' => __('Your payment of :amount has been approved. Your subscription is active until :date.', [
|
|
'amount' => 'R$ ' . number_format($subscription->plan->price, 2, ',', '.'),
|
|
'date' => $subscription->end_date->format('d/m/Y'),
|
|
]),
|
|
]);
|
|
|
|
return back()->with('success', __('Payment approved. Invoice generated and user notified.'));
|
|
}
|
|
|
|
public function cancelSubscription(UserSubscription $subscription): RedirectResponse
|
|
{
|
|
$subscription->update(['status' => 'cancelled', 'cancelled_at' => now()]);
|
|
|
|
UserNotification::create([
|
|
'user_id' => $subscription->user_id,
|
|
'type' => 'admin_message',
|
|
'title' => __('Subscription Cancelled'),
|
|
'message' => __('Your subscription has been cancelled by the administrator.'),
|
|
]);
|
|
|
|
return back()->with('success', __('Subscription cancelled.'));
|
|
}
|
|
|
|
public function invoices(): View
|
|
{
|
|
$invoices = Invoice::with(['user', 'subscription.plan'])
|
|
->orderByDesc('created_at')
|
|
->paginate(20);
|
|
|
|
return view('superadmin.billing.invoices', compact('invoices'));
|
|
}
|
|
|
|
public function downloadInvoice(Invoice $invoice)
|
|
{
|
|
if ($invoice->pdf_path && Storage::exists($invoice->pdf_path)) {
|
|
return Storage::download($invoice->pdf_path, "invoice-{$invoice->invoice_number}.pdf");
|
|
}
|
|
|
|
// Generate on the fly
|
|
$this->generateInvoicePdf($invoice);
|
|
|
|
return Storage::download($invoice->pdf_path, "invoice-{$invoice->invoice_number}.pdf");
|
|
}
|
|
|
|
private function generateInvoicePdf(Invoice $invoice): void
|
|
{
|
|
$pdf = Pdf::loadView('pdf.invoice', compact('invoice'));
|
|
$path = "invoices/invoice-{$invoice->invoice_number}.pdf";
|
|
Storage::put($path, $pdf->output());
|
|
$invoice->update(['pdf_path' => $path]);
|
|
}
|
|
} |