ensurePackages(); [$weddingType, $corporateType] = $this->ensureEventTypes(); $this->seedOnboardingTenant(); $this->seedActiveTenant($standard, $premium, $weddingType, $corporateType); $this->seedResellerTenant($reseller, $standard, $weddingType); $this->seedDormantTenant(); } private function ensurePackages(): array { $standard = Package::firstOrCreate( ['slug' => 'standard'], [ 'type' => 'endcustomer', 'name' => 'Standard', 'name_translations' => ['de' => 'Standard', 'en' => 'Standard'], 'price' => 79, 'max_photos' => 1500, 'max_guests' => 400, 'gallery_days' => 60, 'watermark_allowed' => false, 'branding_allowed' => false, 'features' => [ 'basic_uploads' => true, 'unlimited_sharing' => true, 'custom_tasks' => true, ], ] ); $premium = Package::firstOrCreate( ['slug' => 'premium'], [ 'type' => 'endcustomer', 'name' => 'Premium', 'name_translations' => ['de' => 'Premium', 'en' => 'Premium'], 'price' => 149, 'max_photos' => 5000, 'max_guests' => 1000, 'gallery_days' => 180, 'watermark_allowed' => false, 'branding_allowed' => true, 'features' => [ 'basic_uploads' => true, 'unlimited_sharing' => true, 'custom_branding' => true, 'custom_tasks' => true, ], ] ); $reseller = Package::firstOrCreate( ['slug' => 'studio-annual'], [ 'type' => 'reseller', 'name' => 'Studio Jahrespaket', 'name_translations' => ['de' => 'Studio Jahrespaket', 'en' => 'Studio Annual'], 'price' => 1299, 'max_events_per_year' => 24, 'watermark_allowed' => false, 'branding_allowed' => true, 'features' => [ 'custom_branding' => true, 'unlimited_sharing' => true, 'basic_uploads' => true, ], ] ); return [$standard, $premium, $reseller]; } private function ensureEventTypes(): array { $weddingType = EventType::firstOrCreate( ['slug' => 'wedding'], [ 'name' => 'Wedding', 'name_translations' => ['de' => 'Hochzeit', 'en' => 'Wedding'], 'icon' => 'heart', ] ); $corporateType = EventType::firstOrCreate( ['slug' => 'corporate'], [ 'name' => 'Corporate Event', 'name_translations' => ['de' => 'Firmen-Event', 'en' => 'Corporate'], 'icon' => 'presentation-chart', ] ); return [$weddingType, $corporateType]; } private function seedOnboardingTenant(): void { $tenant = $this->createTenant('storycraft-weddings', [ 'name' => 'Storycraft Weddings', 'contact_email' => 'hello@storycraft-weddings.demo', 'subscription_tier' => 'free', 'subscription_status' => 'free', 'subscription_expires_at' => null, 'is_active' => true, ]); $this->createTenantAdmin($tenant, 'storycraft-owner@demo.fotospiel'); } private function seedActiveTenant(Package $standard, Package $premium, EventType $weddingType, EventType $corporateType): void { $tenant = $this->createTenant('lumen-moments', [ 'name' => 'Lumen Moments', 'contact_email' => 'hello@lumen-moments.demo', 'subscription_tier' => 'starter', 'subscription_status' => 'active', 'is_active' => true, ]); $this->createTenantAdmin($tenant, 'hello@lumen-moments.demo'); $purchase = PackagePurchase::create([ 'tenant_id' => $tenant->id, 'package_id' => $premium->id, 'provider' => 'stripe', 'provider_id' => 'stripe_demo_pi', 'price' => $premium->price, 'type' => 'endcustomer_event', 'purchased_at' => Carbon::now()->subDays(3), 'metadata' => ['demo' => true], ]); $publishedEvent = $this->createEventWithPackage( tenant: $tenant, package: $premium, eventType: $weddingType, attributes: [ 'name' => ['de' => 'Sommerhochzeit Lea & Tim', 'en' => 'Summer Wedding Lea & Tim'], 'slug' => 'summer-wedding-lea-tim', 'status' => 'published', 'is_active' => true, 'date' => Carbon::now()->addWeeks(4), ] ); $draftEvent = $this->createEventWithPackage( tenant: $tenant, package: $standard, eventType: $corporateType, attributes: [ 'name' => ['de' => 'Startup Social 2025', 'en' => 'Startup Social 2025'], 'slug' => 'startup-social-2025', 'status' => 'draft', 'is_active' => false, 'date' => Carbon::now()->addWeeks(12), ] ); $purchase->update(['event_id' => $publishedEvent->id]); PackagePurchase::create([ 'tenant_id' => $tenant->id, 'event_id' => $draftEvent->id, 'package_id' => $standard->id, 'provider' => 'paypal', 'provider_id' => 'paypal_demo_capture', 'price' => $standard->price, 'type' => 'endcustomer_event', 'purchased_at' => Carbon::now()->subDays(1), 'metadata' => ['demo' => true], ]); } private function seedResellerTenant(Package $reseller, Package $standard, EventType $weddingType): void { $tenant = $this->createTenant('viewfinder-studios', [ 'name' => 'Viewfinder Studios', 'contact_email' => 'team@viewfinder.demo', 'subscription_tier' => 'reseller', 'subscription_status' => 'active', 'is_active' => true, ]); $this->createTenantAdmin($tenant, 'team@viewfinder.demo'); $tenantPackage = TenantPackage::create([ 'tenant_id' => $tenant->id, 'package_id' => $reseller->id, 'price' => $reseller->price, 'purchased_at' => Carbon::now()->subMonths(2), 'expires_at' => Carbon::now()->addMonths(10), 'used_events' => 6, 'active' => true, ]); PackagePurchase::create([ 'tenant_id' => $tenant->id, 'package_id' => $reseller->id, 'provider' => 'stripe', 'provider_id' => 'stripe_demo_subscription', 'price' => $reseller->price, 'type' => 'reseller_subscription', 'purchased_at' => $tenantPackage->purchased_at, 'metadata' => ['demo' => true, 'plan' => 'studio-annual'], ]); // Create a mix of events representing allowance consumption. $statuses = ['published', 'published', 'draft', 'archived']; foreach ($statuses as $index => $status) { $event = $this->createEventWithPackage( tenant: $tenant, package: $standard, eventType: $weddingType, attributes: [ 'name' => ['de' => 'Studio Event #'.($index + 1), 'en' => 'Studio Event #'.($index + 1)], 'slug' => 'studio-event-'.($index + 1), 'status' => $status, 'is_active' => $status === 'published', 'date' => $status === 'archived' ? Carbon::now()->subMonths(3) : Carbon::now()->addWeeks($index * 3 + 1), ] ); PackagePurchase::create([ 'tenant_id' => $tenant->id, 'event_id' => $event->id, 'package_id' => $standard->id, 'provider' => 'manual', 'provider_id' => 'reseller_allowance', 'price' => 0, 'type' => 'endcustomer_event', 'purchased_at' => Carbon::now()->subDays(10 - $index), 'metadata' => ['allowance' => true], ]); } } private function seedDormantTenant(): void { $tenant = $this->createTenant('pixel-and-co', [ 'name' => 'Pixel & Co', 'contact_email' => 'support@pixelco.demo', 'subscription_status' => 'expired', 'subscription_tier' => 'free', 'subscription_expires_at' => Carbon::now()->subMonths(2), 'is_active' => false, 'is_suspended' => false, ]); $this->createTenantAdmin($tenant, 'support@pixelco.demo', role: 'member'); } private function createTenantAdmin(Tenant $tenant, string $email, string $role = 'tenant_admin'): User { return User::updateOrCreate( ['email' => $email], [ 'tenant_id' => $tenant->id, 'role' => $role, 'password' => Hash::make('Demo1234!'), 'first_name' => Str::headline(Str::before($tenant->slug, '-')), 'last_name' => 'Team', ] ); } private function createEventWithPackage( Tenant $tenant, Package $package, EventType $eventType, array $attributes ): Event { $payload = array_merge([ 'tenant_id' => $tenant->id, 'event_type_id' => $eventType->id, 'settings' => [ 'features' => [ 'photo_likes_enabled' => true, 'event_checklist' => true, ], ], ], $attributes); $event = Event::updateOrCreate(['slug' => $attributes['slug']], $payload); EventPackage::updateOrCreate( [ 'event_id' => $event->id, 'package_id' => $package->id, ], [ 'purchased_price' => $package->price, 'purchased_at' => Carbon::now()->subDays(2), 'used_photos' => 0, 'used_guests' => 0, 'gallery_expires_at' => Carbon::now()->addDays($package->gallery_days ?? 30), ] ); return $event; } private function createTenant(string $slug, array $overrides = []): Tenant { $email = $overrides['contact_email'] ?? $slug.'@demo.fotospiel'; $defaults = [ 'name' => Str::headline(str_replace('-', ' ', $slug)), 'slug' => $slug, 'contact_email' => $email, 'event_credits_balance' => 0, 'subscription_tier' => 'free', 'subscription_status' => 'free', 'subscription_expires_at' => Carbon::now()->addMonths(6), 'is_active' => true, 'is_suspended' => false, 'settings_updated_at' => Carbon::now(), 'settings' => $this->defaultSettings($email), ]; $attributes = array_merge($defaults, $overrides); $tenant = Tenant::updateOrCreate(['slug' => $slug], $attributes); return $tenant; } private function defaultSettings(string $contactEmail): array { return [ 'branding' => [ 'logo_url' => null, 'primary_color' => '#3B82F6', 'secondary_color' => '#1F2937', 'font_family' => 'Inter, sans-serif', ], 'features' => [ 'photo_likes_enabled' => true, 'event_checklist' => true, 'custom_domain' => false, 'advanced_analytics' => false, ], 'custom_domain' => null, 'contact_email' => $contactEmail, 'event_default_type' => 'general', ]; } }