Central panel SaaS upgrade — Plans/Subscriptions/SuperAdmins/Detail page
Models & migrations: - subscriptions table (company, plan, period, amount, status, dates, invoice) - super_admins: role enum (owner/admin/support/sales/finance) + phone + notes - Subscription model with STATUSES/PERIODS/PAYMENT_METHODS + invoice number generator + extends company.active_until on mark_paid - Company model: subscriptions() + latestSubscription() relations - SuperAdmin model: role helpers (isOwner, canManageBilling, canManageTenants) Filament Central panel: - PlanResource (CRUD, features checklist, limits per plan, abonati count badge) - SubscriptionResource (CRUD, mark_paid action, navigation badge for overdue) - SuperAdminResource (CRUD, reset password, toggle 2FA, can't self-delete) - ViewCompany page with live stats (users/clients/vehicles/WO/parts/revenue/ storage/last_login + days_until_expiry), subscriptions history table, config snapshot, action buttons (open/issue invoice/upload logo/suspend) - CompanyResource: row click → view, openUrlInNewTab action, recordTitleAttribute, empty state, view route registered - PlatformStats widget upgraded: 6 cards (incl. MRR realized this month, overdue invoices count, click-through to filtered tables) - RevenueChart: 12-month MRR line chart - RecentTenants: latest 8 tenants with click-through - PendingPayments: pending+overdue invoices table - Database notifications enabled + Cmd+K global search - HEAD_END render hook: PWA manifest + theme color + emoji favicon - /admin-manifest.json route Seeder: - Plans aligned with new FEATURE_OPTIONS (kanban/pdf/reports/ai/api/reverb/etc) - 4 plans: Free / Basic / Pro / Enterprise (with proper limits) - SuperAdmin gets role='owner' - Demo subscription for psauto on Pro plan, marked paid this month
This commit is contained in:
@@ -39,25 +39,41 @@ class DatabaseSeeder extends Seeder
|
||||
$free = Plan::firstOrCreate(['slug' => 'free'], [
|
||||
'name' => 'Free',
|
||||
'price_monthly' => 0,
|
||||
'price_yearly' => 0,
|
||||
'currency' => 'MDL',
|
||||
'features' => ['core'],
|
||||
'limits' => ['max_users' => 2, 'max_vehicles' => 50],
|
||||
'features' => ['kanban'],
|
||||
'limits' => ['max_users' => 2, 'max_vehicles' => 50, 'max_clients' => 100, 'storage_mb' => 100],
|
||||
'is_active' => true, 'is_public' => true,
|
||||
]);
|
||||
|
||||
Plan::firstOrCreate(['slug' => 'basic'], [
|
||||
'name' => 'Basic',
|
||||
'price_monthly' => 299,
|
||||
'price_yearly' => 2990,
|
||||
'currency' => 'MDL',
|
||||
'features' => ['core', 'workorders', 'kanban'],
|
||||
'limits' => ['max_users' => 5, 'max_vehicles' => 500],
|
||||
'features' => ['kanban', 'pdf', 'reports'],
|
||||
'limits' => ['max_users' => 5, 'max_vehicles' => 500, 'max_clients' => 1000, 'storage_mb' => 1000],
|
||||
'is_active' => true, 'is_public' => true,
|
||||
]);
|
||||
|
||||
Plan::firstOrCreate(['slug' => 'pro'], [
|
||||
'name' => 'Pro',
|
||||
'price_monthly' => 599,
|
||||
'price_yearly' => 5990,
|
||||
'currency' => 'MDL',
|
||||
'features' => ['core', 'workorders', 'kanban', 'reports', 'ai', 'api'],
|
||||
'limits' => ['max_users' => -1, 'max_vehicles' => -1],
|
||||
'features' => ['kanban', 'pdf', 'reports', 'ai', 'api', 'reverb', 'multi_user', 'white_label'],
|
||||
'limits' => ['max_users' => 20, 'max_vehicles' => 5000, 'max_clients' => 10000, 'storage_mb' => 10000, 'ai_messages_month' => 1000],
|
||||
'is_active' => true, 'is_public' => true,
|
||||
]);
|
||||
|
||||
Plan::firstOrCreate(['slug' => 'enterprise'], [
|
||||
'name' => 'Enterprise',
|
||||
'price_monthly' => 1499,
|
||||
'price_yearly' => 14990,
|
||||
'currency' => 'MDL',
|
||||
'features' => ['kanban', 'pdf', 'reports', 'ai', 'api', 'reverb', 'multi_user', 'white_label', 'priority_support', 'custom_domain'],
|
||||
'limits' => [],
|
||||
'is_active' => true, 'is_public' => true,
|
||||
]);
|
||||
|
||||
// ─── Super-admin (operator platformă) ─────────────────────
|
||||
@@ -65,8 +81,29 @@ class DatabaseSeeder extends Seeder
|
||||
'name' => 'Vasyka',
|
||||
'password' => Hash::make('admin123'),
|
||||
'is_active' => true,
|
||||
'role' => 'owner',
|
||||
]);
|
||||
|
||||
// ─── Subscription demo (PSauto pe Pro plan, plătit) ──────
|
||||
$proPlan = Plan::where('slug', 'pro')->first();
|
||||
$psautoCompany = Company::where('slug', 'psauto')->first();
|
||||
if ($proPlan && $psautoCompany) {
|
||||
\App\Models\Central\Subscription::firstOrCreate(
|
||||
['company_id' => $psautoCompany->id, 'period_start' => today()->startOfMonth()],
|
||||
[
|
||||
'plan_id' => $proPlan->id,
|
||||
'period' => 'monthly',
|
||||
'amount' => $proPlan->price_monthly,
|
||||
'currency' => 'MDL',
|
||||
'status' => 'paid',
|
||||
'period_end' => today()->endOfMonth(),
|
||||
'paid_at' => today()->startOfMonth()->addDay(),
|
||||
'invoice_number' => 'INV-' . date('Ym') . '-0001',
|
||||
'payment_method' => 'bank_transfer',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// ─── PSauto demo company ──────────────────────────────────
|
||||
$psauto = Company::firstOrCreate(['slug' => 'psauto'], [
|
||||
'name' => 'PSauto SRL',
|
||||
|
||||
Reference in New Issue
Block a user