Idempotent provisioning, service soft-delete, Plans page redesign, doc updates
Part A: Fix duplicate Service creation on provisioning retry - All 4 provisioning services use Service::firstOrCreate() keyed on subscription_id+service_type to prevent duplicates on queue retries - HandleSubscriptionCreated sends notification before provisioning, no longer re-throws on failure - RetryProvisioningCommand simplified to reuse existing Service records Part B: Plans/Pricing page complete redesign - Service type tabs (VPS, Dedicated, Web Hosting, MySQL) - Billing cycle segmented toggle (monthly/quarterly/semi-annual/annual) - Feature icons per service type, Popular/Best Value badges - Stock indicators, effective monthly price calculations Part C: Admin service soft-delete/archive - Service model uses SoftDeletes trait - Admin can archive and restore services - Show archived toggle on services list - Migration adds deleted_at column Docs: Updated TASKS.md, CLAUDE.md, PROJECT_DEVELOPMENT.md, MEMORY.md - Phase 3 marked complete, test counts updated (252 passing) - SupportPal references replaced with standalone ticket system - Frontend design skill background rule added - Closed GitHub issues #3, #6, #7, #8, #9 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,39 +42,39 @@ class DemoDataSeeder extends Seeder
|
||||
$adminUser = User::role('admin')->first();
|
||||
$adminId = $adminUser?->id ?? 1;
|
||||
|
||||
// ─── 1. Create ~300 Customers ─────────────────────────────────
|
||||
// ─── 1. Create 1000 Customers ─────────────────────────────────
|
||||
$this->command->info('Creating customers...');
|
||||
$customers = $this->createCustomers();
|
||||
|
||||
// ─── 2. Create ~500 Subscriptions ─────────────────────────────
|
||||
// ─── 2. Create ~1500 Subscriptions ────────────────────────────
|
||||
$this->command->info('Creating subscriptions...');
|
||||
$subscriptionMap = $this->createSubscriptions($customers, $plans);
|
||||
|
||||
// ─── 3. Create ~400 Services ──────────────────────────────────
|
||||
// ─── 3. Create ~1200 Services (70% VPS) ───────────────────────
|
||||
$this->command->info('Creating services...');
|
||||
$this->createServices($customers, $plans, $subscriptionMap);
|
||||
|
||||
// ─── 4. Create ~800 Invoices with Items ───────────────────────
|
||||
// ─── 4. Create ~2000 Invoices with Items ──────────────────────
|
||||
$this->command->info('Creating invoices...');
|
||||
$invoiceIds = $this->createInvoices($customers, $plans, $subscriptionMap);
|
||||
|
||||
// ─── 5. Create ~600 Payment Transactions ──────────────────────
|
||||
// ─── 5. Create ~1500 Payment Transactions ─────────────────────
|
||||
$this->command->info('Creating payment transactions...');
|
||||
$this->createPaymentTransactions($customers, $invoiceIds);
|
||||
|
||||
// ─── 6. Create ~150 Orders ────────────────────────────────────
|
||||
// ─── 6. Create ~400 Orders ────────────────────────────────────
|
||||
$this->command->info('Creating orders...');
|
||||
$this->createOrders($customers, $plans);
|
||||
|
||||
// ─── 7. Create ~200 Support Tickets with Replies ──────────────
|
||||
// ─── 7. Create ~500 Support Tickets with Replies ──────────────
|
||||
$this->command->info('Creating support tickets...');
|
||||
$this->createSupportTickets($customers, $adminId);
|
||||
|
||||
// ─── 8. Create ~50 Coupons ────────────────────────────────────
|
||||
// ─── 8. Create ~100 Coupons ───────────────────────────────────
|
||||
$this->command->info('Creating coupons...');
|
||||
$this->createCoupons();
|
||||
|
||||
// ─── 9. Create ~100 Audit Logs ────────────────────────────────
|
||||
// ─── 9. Create ~300 Audit Logs ────────────────────────────────
|
||||
$this->command->info('Creating audit logs...');
|
||||
$this->createAuditLogs($customers, $adminId);
|
||||
|
||||
@@ -82,7 +82,7 @@ class DemoDataSeeder extends Seeder
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ~300 customers with profiles.
|
||||
* Create 1000 customers with profiles.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection<int, User>
|
||||
*/
|
||||
@@ -90,16 +90,16 @@ class DemoDataSeeder extends Seeder
|
||||
{
|
||||
$customers = collect();
|
||||
$statuses = array_merge(
|
||||
array_fill(0, 270, 'active'),
|
||||
array_fill(0, 15, 'suspended'),
|
||||
array_fill(0, 10, 'banned'),
|
||||
array_fill(0, 5, 'pending'),
|
||||
array_fill(0, 900, 'active'),
|
||||
array_fill(0, 50, 'suspended'),
|
||||
array_fill(0, 30, 'banned'),
|
||||
array_fill(0, 20, 'pending'),
|
||||
);
|
||||
shuffle($statuses);
|
||||
|
||||
$faker = fake();
|
||||
$batchSize = 50;
|
||||
$totalCustomers = 300;
|
||||
$batchSize = 100;
|
||||
$totalCustomers = 1000;
|
||||
|
||||
for ($i = 0; $i < $totalCustomers; $i += $batchSize) {
|
||||
$batchCount = min($batchSize, $totalCustomers - $i);
|
||||
@@ -138,7 +138,7 @@ class DemoDataSeeder extends Seeder
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ~500 subscriptions linked to real plans.
|
||||
* Create ~1500 subscriptions linked to real plans (70% VPS).
|
||||
*
|
||||
* Returns a map of subscription_id => [user_id, plan_id] for use by other seeders.
|
||||
*
|
||||
@@ -150,12 +150,19 @@ class DemoDataSeeder extends Seeder
|
||||
{
|
||||
$subscriptionMap = [];
|
||||
$statuses = ['active', 'active', 'active', 'active', 'active', 'active', 'active', 'canceled', 'past_due', 'trialing'];
|
||||
$total = 500;
|
||||
$total = 1500;
|
||||
|
||||
// Separate plans by type for weighted distribution
|
||||
$vpsPlans = $plans->where('service_type', 'vps');
|
||||
$otherPlans = $plans->whereNotIn('service_type', ['vps']);
|
||||
$rows = [];
|
||||
|
||||
for ($i = 0; $i < $total; $i++) {
|
||||
$customer = $customers->random();
|
||||
$plan = $plans->random();
|
||||
// 70% VPS, 30% other services
|
||||
$plan = (rand(1, 100) <= 70 && $vpsPlans->isNotEmpty())
|
||||
? $vpsPlans->random()
|
||||
: ($otherPlans->isNotEmpty() ? $otherPlans->random() : $plans->random());
|
||||
$status = $statuses[array_rand($statuses)];
|
||||
$createdAt = $customer->created_at->copy()->addDays(rand(0, 60));
|
||||
|
||||
@@ -243,21 +250,28 @@ class DemoDataSeeder extends Seeder
|
||||
];
|
||||
|
||||
$serviceStatuses = array_merge(
|
||||
array_fill(0, 300, 'active'),
|
||||
array_fill(0, 40, 'suspended'),
|
||||
array_fill(0, 30, 'pending'),
|
||||
array_fill(0, 30, 'terminated'),
|
||||
array_fill(0, 1000, 'active'),
|
||||
array_fill(0, 100, 'suspended'),
|
||||
array_fill(0, 50, 'pending'),
|
||||
array_fill(0, 50, 'terminated'),
|
||||
);
|
||||
shuffle($serviceStatuses);
|
||||
|
||||
$subIds = array_keys($subscriptionMap);
|
||||
$rows = [];
|
||||
$faker = fake();
|
||||
$total = 400;
|
||||
$total = 1200;
|
||||
|
||||
// Separate plans by type for weighted distribution
|
||||
$vpsPlans = $plans->where('service_type', 'vps');
|
||||
$otherPlans = $plans->whereNotIn('service_type', ['vps']);
|
||||
|
||||
for ($i = 0; $i < $total; $i++) {
|
||||
$customer = $customers->random();
|
||||
$plan = $plans->random();
|
||||
// 70% VPS, 30% other services
|
||||
$plan = (rand(1, 100) <= 70 && $vpsPlans->isNotEmpty())
|
||||
? $vpsPlans->random()
|
||||
: ($otherPlans->isNotEmpty() ? $otherPlans->random() : $plans->random());
|
||||
$status = $serviceStatuses[$i] ?? 'active';
|
||||
$serviceType = $plan->service_type;
|
||||
$platform = $platformMap[$serviceType] ?? 'virtfusion';
|
||||
@@ -310,7 +324,7 @@ class DemoDataSeeder extends Seeder
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ~800 invoices with line items.
|
||||
* Create ~2000 invoices with line items.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection<int, User> $customers
|
||||
* @param \Illuminate\Support\Collection<int, Plan> $plans
|
||||
@@ -320,10 +334,10 @@ class DemoDataSeeder extends Seeder
|
||||
private function createInvoices(\Illuminate\Support\Collection $customers, \Illuminate\Support\Collection $plans, array $subscriptionMap): array
|
||||
{
|
||||
$invoiceStatuses = array_merge(
|
||||
array_fill(0, 500, 'paid'),
|
||||
array_fill(0, 150, 'pending'),
|
||||
array_fill(0, 100, 'overdue'),
|
||||
array_fill(0, 50, 'void'),
|
||||
array_fill(0, 1400, 'paid'),
|
||||
array_fill(0, 300, 'pending'),
|
||||
array_fill(0, 200, 'overdue'),
|
||||
array_fill(0, 100, 'void'),
|
||||
);
|
||||
shuffle($invoiceStatuses);
|
||||
|
||||
@@ -331,7 +345,7 @@ class DemoDataSeeder extends Seeder
|
||||
$invoiceRows = [];
|
||||
$invoiceTracker = [];
|
||||
$faker = fake();
|
||||
$total = 800;
|
||||
$total = 2000;
|
||||
|
||||
for ($i = 0; $i < $total; $i++) {
|
||||
$customer = $customers->random();
|
||||
@@ -449,17 +463,17 @@ class DemoDataSeeder extends Seeder
|
||||
{
|
||||
$rows = [];
|
||||
$faker = fake();
|
||||
$total = 600;
|
||||
$total = 1500;
|
||||
|
||||
// Use paid/pending invoices for payment transactions
|
||||
$paidInvoices = array_filter($invoiceData, fn ($inv) => $inv['status'] === 'paid');
|
||||
$paidInvoices = array_values($paidInvoices);
|
||||
|
||||
$transactionStatuses = array_merge(
|
||||
array_fill(0, 480, 'succeeded'),
|
||||
array_fill(0, 60, 'failed'),
|
||||
array_fill(0, 40, 'refunded'),
|
||||
array_fill(0, 20, 'pending'),
|
||||
array_fill(0, 1200, 'succeeded'),
|
||||
array_fill(0, 150, 'failed'),
|
||||
array_fill(0, 100, 'refunded'),
|
||||
array_fill(0, 50, 'pending'),
|
||||
);
|
||||
shuffle($transactionStatuses);
|
||||
|
||||
@@ -522,16 +536,16 @@ class DemoDataSeeder extends Seeder
|
||||
private function createOrders(\Illuminate\Support\Collection $customers, \Illuminate\Support\Collection $plans): void
|
||||
{
|
||||
$orderStatuses = array_merge(
|
||||
array_fill(0, 80, 'completed'),
|
||||
array_fill(0, 30, 'pending'),
|
||||
array_fill(0, 25, 'processing'),
|
||||
array_fill(0, 15, 'cancelled'),
|
||||
array_fill(0, 250, 'completed'),
|
||||
array_fill(0, 70, 'pending'),
|
||||
array_fill(0, 50, 'processing'),
|
||||
array_fill(0, 30, 'cancelled'),
|
||||
);
|
||||
shuffle($orderStatuses);
|
||||
|
||||
$rows = [];
|
||||
$faker = fake();
|
||||
$total = 150;
|
||||
$total = 400;
|
||||
|
||||
for ($i = 0; $i < $total; $i++) {
|
||||
$customer = $customers->random();
|
||||
@@ -610,15 +624,15 @@ class DemoDataSeeder extends Seeder
|
||||
];
|
||||
|
||||
$ticketStatuses = array_merge(
|
||||
array_fill(0, 60, 'open'),
|
||||
array_fill(0, 50, 'in_progress'),
|
||||
array_fill(0, 40, 'waiting'),
|
||||
array_fill(0, 50, 'closed'),
|
||||
array_fill(0, 150, 'open'),
|
||||
array_fill(0, 125, 'in_progress'),
|
||||
array_fill(0, 100, 'waiting'),
|
||||
array_fill(0, 125, 'closed'),
|
||||
);
|
||||
shuffle($ticketStatuses);
|
||||
|
||||
$priorities = ['low', 'low', 'medium', 'medium', 'medium', 'high', 'high', 'urgent'];
|
||||
$total = 200;
|
||||
$total = 500;
|
||||
|
||||
$ticketRows = [];
|
||||
$ticketMeta = [];
|
||||
@@ -746,7 +760,7 @@ class DemoDataSeeder extends Seeder
|
||||
'PARTNER', 'AGENCY', 'RESELLER', 'BULK', 'ENTERPRISE',
|
||||
];
|
||||
|
||||
$total = 50;
|
||||
$total = 100;
|
||||
|
||||
for ($i = 0; $i < $total; $i++) {
|
||||
$type = $faker->randomElement(['percentage', 'percentage', 'fixed_amount']);
|
||||
@@ -820,7 +834,7 @@ class DemoDataSeeder extends Seeder
|
||||
|
||||
$faker = fake();
|
||||
$rows = [];
|
||||
$total = 100;
|
||||
$total = 300;
|
||||
|
||||
$userAgents = [
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
|
||||
|
||||
@@ -11,181 +11,193 @@ class PlanSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
Plan::query()->delete();
|
||||
// Archive old VPS plans instead of deleting (preserves foreign key relationships)
|
||||
Plan::query()
|
||||
->where('service_type', 'vps')
|
||||
->whereNotIn('slug', [
|
||||
'vps-nano', 'vps-micro', 'vps-mini', 'vps-standard',
|
||||
'vps-plus', 'vps-pro', 'vps-storage-500', 'vps-storage-1tb',
|
||||
])
|
||||
->update(['status' => 'archived']);
|
||||
|
||||
$plans = [
|
||||
// ─── VPS Plans ───────────────────────────────────────────────
|
||||
// ─── VPS Plans (2026 NVMe Lineup) ────────────────────────────
|
||||
[
|
||||
'name' => 'Micro VPS',
|
||||
'slug' => 'micro-vps',
|
||||
'description' => 'Lightweight VPS for simple tasks, testing, and small projects.',
|
||||
'name' => 'Nano',
|
||||
'slug' => 'vps-nano',
|
||||
'description' => 'Entry-level NVMe VPS for simple tasks, testing, and lightweight applications.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 4.20,
|
||||
'price' => 3.50,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '1 vCPU',
|
||||
'ram' => '1 GB',
|
||||
'storage' => '25 GB SSD',
|
||||
'storage' => '15 GB NVMe',
|
||||
'bandwidth' => '2 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'Mini VPS',
|
||||
'slug' => 'mini-vps',
|
||||
'description' => 'Compact VPS with extra memory for light workloads.',
|
||||
'name' => 'Micro',
|
||||
'slug' => 'vps-micro',
|
||||
'description' => 'NVMe VPS with 2 GB RAM - double the RAM of competitors at the same price point.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 6.00,
|
||||
'price' => 5.95,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '1 vCPU',
|
||||
'ram' => '2 GB',
|
||||
'storage' => '50 GB SSD',
|
||||
'bandwidth' => '4 TB',
|
||||
'storage' => '30 GB NVMe',
|
||||
'bandwidth' => '3 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 2,
|
||||
],
|
||||
[
|
||||
'name' => 'Dev Starter',
|
||||
'slug' => 'dev-starter',
|
||||
'description' => 'Dual-core VPS ideal for development environments and staging.',
|
||||
'name' => 'Mini',
|
||||
'slug' => 'vps-mini',
|
||||
'description' => 'Hero plan with 4 GB RAM and NVMe storage - beats Hetzner CX22 with faster disks.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 8.00,
|
||||
'price' => 8.95,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '2 vCPU',
|
||||
'ram' => '2 GB',
|
||||
'storage' => '60 GB SSD',
|
||||
'ram' => '4 GB',
|
||||
'storage' => '50 GB NVMe',
|
||||
'bandwidth' => '4 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 3,
|
||||
],
|
||||
[
|
||||
'name' => 'Basic VPS',
|
||||
'slug' => 'basic-vps',
|
||||
'description' => 'Balanced VPS for web apps, databases, and general-purpose workloads.',
|
||||
'name' => 'Standard',
|
||||
'slug' => 'vps-standard',
|
||||
'description' => 'Premium 8 GB RAM VPS with NVMe - double the RAM of competitors at half the price.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 12.00,
|
||||
'price' => 14.95,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '2 vCPU',
|
||||
'ram' => '4 GB',
|
||||
'storage' => '80 GB SSD',
|
||||
'ram' => '8 GB',
|
||||
'storage' => '80 GB NVMe',
|
||||
'bandwidth' => '6 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 4,
|
||||
],
|
||||
[
|
||||
'name' => 'Storage Box',
|
||||
'slug' => 'storage-box',
|
||||
'description' => 'High-storage VPS for backups, media, and file-heavy applications.',
|
||||
'name' => 'Plus',
|
||||
'slug' => 'vps-plus',
|
||||
'description' => 'High-RAM VPS with 12 GB memory and quad-core CPU for demanding applications.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 15.00,
|
||||
'price' => 22.95,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '4 vCPU',
|
||||
'ram' => '12 GB',
|
||||
'storage' => '120 GB NVMe',
|
||||
'bandwidth' => '8 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 5,
|
||||
],
|
||||
[
|
||||
'name' => 'Pro',
|
||||
'slug' => 'vps-pro',
|
||||
'description' => 'Ultimate RAM VPS with 16 GB memory and NVMe for production workloads.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 29.95,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '4 vCPU',
|
||||
'ram' => '16 GB',
|
||||
'storage' => '160 GB NVMe',
|
||||
'bandwidth' => '10 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 6,
|
||||
],
|
||||
[
|
||||
'name' => 'Storage-500',
|
||||
'slug' => 'vps-storage-500',
|
||||
'description' => 'Storage-focused VPS with 500 GB SATA SSD for backups, media, and file storage.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 24.95,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '2 vCPU',
|
||||
'ram' => '2 GB',
|
||||
'ram' => '4 GB',
|
||||
'storage' => '500 GB SSD',
|
||||
'bandwidth' => '8 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
],
|
||||
'sort_order' => 5,
|
||||
],
|
||||
[
|
||||
'name' => 'Standard VPS',
|
||||
'slug' => 'standard-vps',
|
||||
'description' => 'Quad-core VPS with 8 GB RAM for production applications.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 15.60,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '4 vCPU',
|
||||
'ram' => '8 GB',
|
||||
'storage' => '160 GB SSD',
|
||||
'bandwidth' => '8 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
],
|
||||
'sort_order' => 6,
|
||||
],
|
||||
[
|
||||
'name' => 'RAM Optimized',
|
||||
'slug' => 'ram-optimized',
|
||||
'description' => 'Memory-optimized VPS for databases, caching, and in-memory workloads.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 19.00,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '4 vCPU',
|
||||
'ram' => '16 GB',
|
||||
'storage' => '240 GB SSD',
|
||||
'bandwidth' => '10 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 7,
|
||||
],
|
||||
[
|
||||
'name' => 'Advanced VPS',
|
||||
'slug' => 'advanced-vps',
|
||||
'description' => 'Six-core VPS with 16 GB RAM for demanding applications and multi-service setups.',
|
||||
'name' => 'Storage-1TB',
|
||||
'slug' => 'vps-storage-1tb',
|
||||
'description' => 'Mass storage VPS with 1 TB SATA SSD for large-scale file storage and archives.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 21.60,
|
||||
'price' => 44.95,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '6 vCPU',
|
||||
'ram' => '16 GB',
|
||||
'storage' => '320 GB SSD',
|
||||
'bandwidth' => '10 TB',
|
||||
'cpu' => '4 vCPU',
|
||||
'ram' => '8 GB',
|
||||
'storage' => '1 TB SSD',
|
||||
'bandwidth' => '12 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
'virtfusion_package_id' => 1,
|
||||
'virtfusion_user_id' => 1,
|
||||
'virtfusion_hypervisor_id' => 1,
|
||||
],
|
||||
'sort_order' => 8,
|
||||
],
|
||||
[
|
||||
'name' => 'Pro VPS',
|
||||
'slug' => 'pro-vps',
|
||||
'description' => 'Eight-core powerhouse with 32 GB RAM for enterprise workloads and heavy traffic.',
|
||||
'service_type' => 'vps',
|
||||
'price' => 30.00,
|
||||
'billing_cycle' => 'monthly',
|
||||
'features' => [
|
||||
'cpu' => '8 vCPU',
|
||||
'ram' => '32 GB',
|
||||
'storage' => '640 GB SSD',
|
||||
'bandwidth' => '16 TB',
|
||||
'ipv4' => '1 IPv4',
|
||||
'ipv6' => '1 /64 IPv6',
|
||||
'control_panel' => 'VirtFusion',
|
||||
'os' => 'Linux & Windows (BYOL)',
|
||||
],
|
||||
'sort_order' => 9,
|
||||
],
|
||||
|
||||
// ─── Dedicated Server Plans ──────────────────────────────────
|
||||
[
|
||||
|
||||
39
website/database/seeders/UpdateVirtFusionPackageIds.php
Normal file
39
website/database/seeders/UpdateVirtFusionPackageIds.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Plan;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class UpdateVirtFusionPackageIds extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
// Map Laravel plans to VirtFusion package IDs
|
||||
$mapping = [
|
||||
'Nano' => 43, // Base Package (will use custom specs)
|
||||
'Micro' => 19, // Micro
|
||||
'Mini' => 20, // Mini
|
||||
'Standard' => 22, // Standard
|
||||
'Plus' => 23, // Advanced
|
||||
'Pro' => 24, // Pro
|
||||
'Storage-500' => 41, // Storage Box
|
||||
'Storage-1TB' => 41, // Storage Box
|
||||
];
|
||||
|
||||
foreach ($mapping as $planName => $packageId) {
|
||||
$plan = Plan::where('name', $planName)->where('service_type', 'vps')->first();
|
||||
|
||||
if ($plan) {
|
||||
$features = $plan->features ?? [];
|
||||
$features['virtfusion_package_id'] = $packageId;
|
||||
|
||||
$plan->update(['features' => $features]);
|
||||
|
||||
$this->command->info("Updated {$planName} with VirtFusion package ID {$packageId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user