isProduction()) { $this->command->warn('DemoSeeder пропущен: запрещён в production.'); return; } $tenant = Tenant::query()->where('subdomain', 'demo')->first() ?? Tenant::factory()->create([ 'subdomain' => 'demo', 'organization_name' => 'Demo Tenant', 'contact_email' => 'admin@demo.local', 'status' => 'active', 'balance_rub' => '1000.00', 'is_trial' => false, ]); $admin = User::query()->updateOrCreate( ['email' => 'admin@demo.local'], [ 'tenant_id' => $tenant->id, 'password_hash' => Hash::make('password'), 'first_name' => 'Demo', 'last_name' => 'Admin', 'timezone' => 'Europe/Moscow', 'is_active' => true, 'totp_enabled' => false, 'sound_enabled' => true, 'email_verified_at' => now(), 'notification_preferences' => [ 'new_lead' => ['inapp' => true, 'push' => true, 'email' => false], 'reminder' => ['inapp' => true, 'push' => true, 'email' => true], 'low_balance' => ['email' => true], 'zero_balance' => ['email' => true], 'topup_success' => ['email' => true], 'invoice_paid' => ['email' => true], 'new_device_login' => ['email' => true], 'marketing' => ['email' => false], ], ] ); $this->seedProjects($tenant->id); $this->seedDeals($tenant->id, $admin->id); $this->command->info("Demo tenant id={$tenant->id} subdomain=demo"); $this->command->info('Login: admin@demo.local / password'); } private function seedProjects(int $tenantId): void { $now = now(); $projects = [ [ 'tag' => 'site', 'name' => 'Окна СПб (сайт)', 'type' => 'webhook', 'signal_type' => 'site', 'signal_identifier' => 'okna-konkurent.ru', 'sms_senders' => null, 'sms_keyword' => null, 'daily_limit_target' => 50, ], [ 'tag' => 'call', 'name' => 'Натяжные потолки (звонок)', 'type' => 'webhook', 'signal_type' => 'call', 'signal_identifier' => '79161112233', 'sms_senders' => null, 'sms_keyword' => null, 'daily_limit_target' => 30, ], [ 'tag' => 'sms', 'name' => 'Доставка еды (СМС)', 'type' => 'webhook', 'signal_type' => 'sms', 'signal_identifier' => null, 'sms_senders' => json_encode(['EDA-PROMO', 'YAEDA']), 'sms_keyword' => 'скидка', 'daily_limit_target' => 20, ], ]; foreach ($projects as $p) { DB::table('projects')->updateOrInsert( ['tenant_id' => $tenantId, 'name' => $p['name']], [ 'tenant_id' => $tenantId, 'name' => $p['name'], 'tag' => $p['tag'], 'type' => $p['type'], 'signal_type' => $p['signal_type'], 'signal_identifier' => $p['signal_identifier'], 'sms_senders' => $p['sms_senders'], 'sms_keyword' => $p['sms_keyword'], 'is_active' => true, 'daily_limit_target' => $p['daily_limit_target'], 'delivered_today' => 0, 'delivered_in_month' => 0, 'region_mask' => 0, 'region_mode' => 'include', 'delivery_days_mask' => 127, 'assignment_strategy' => 'manual', 'ttfr_target_minutes' => 60, 'created_at' => $now, 'updated_at' => $now, ] ); } } private function seedDeals(int $tenantId, int $managerId): void { $statuses = DB::table('lead_statuses')->orderBy('sort_order')->get(); $projects = DB::table('projects') ->where('tenant_id', $tenantId) ->orderBy('id') ->get() ->keyBy('signal_type'); $samplePool = [ 'site' => [ ['name' => 'Иван Петров', 'phone' => '+79161234501', 'utm' => ['source' => 'yandex', 'medium' => 'cpc', 'campaign' => 'okna-spb']], ['name' => 'Анна Смирнова', 'phone' => '+79161234502', 'utm' => ['source' => 'google', 'medium' => 'organic', 'campaign' => null]], ], 'call' => [ ['name' => 'Сергей Иванов', 'phone' => '+79161234503', 'utm' => ['source' => 'call', 'medium' => 'direct', 'campaign' => null]], ['name' => 'Мария Кузнецова', 'phone' => '+79161234504', 'utm' => ['source' => 'call', 'medium' => 'direct', 'campaign' => null]], ], 'sms' => [ ['name' => 'Дмитрий Соколов', 'phone' => '+79161234505', 'utm' => ['source' => 'sms', 'medium' => 'promo', 'campaign' => 'eda-skidka']], ['name' => 'Елена Морозова', 'phone' => '+79161234506', 'utm' => ['source' => 'sms', 'medium' => 'promo', 'campaign' => 'eda-skidka']], ], ]; $now = now(); $signalCycle = ['site', 'call', 'sms']; $i = 0; foreach ($statuses as $status) { $signal = $signalCycle[$i % 3]; $sample = $samplePool[$signal][$i % 2]; $project = $projects[$signal]; $existing = DB::table('deals') ->where('tenant_id', $tenantId) ->where('phone', $sample['phone']) ->where('status', $status->slug) ->first(); if ($existing) { $i++; continue; } DB::table('deals')->insert([ 'tenant_id' => $tenantId, 'project_id' => $project->id, 'phone' => $sample['phone'], 'phones' => json_encode([$sample['phone']]), 'status' => $status->slug, 'contact_name' => $sample['name'], 'comment' => "Демо-сделка статуса «{$status->name_ru}» ({$signal})", 'manager_id' => $managerId, 'assigned_at' => $now, 'escalated_count' => 0, 'utm_source' => $sample['utm']['source'], 'utm_medium' => $sample['utm']['medium'], 'utm_campaign' => $sample['utm']['campaign'], 'region_code' => $i % 2 === 0 ? '77' : '78', 'city' => $i % 2 === 0 ? 'Москва' : 'Санкт-Петербург', 'time_in_form_seconds' => 30 + $i * 5, 'lead_score' => number_format(50.0 + $i * 3, 2, '.', ''), 'is_test' => false, 'received_at' => $now->copy()->subMinutes($i * 7), 'created_at' => $now, 'updated_at' => $now, ]); $i++; } } }