First Commit

This commit is contained in:
marco
2026-09-01 07:49:48 -03:00
commit 28b1044038
399 changed files with 41659 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
<?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]);
}
}