Tul xxx Tul
User / IP
:
216.73.216.159
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
ventas
/
app
/
Console
/
Commands
/
Viewing: InstallSystem.php
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Schema; class InstallSystem extends Command { protected $signature = 'system:install {--fresh : Eliminar todas las tablas y empezar desde cero} {--backup= : Archivo de backup para restaurar datos (opcional)} {--tenant= : ID del tenant específico (opcional)} {--skip-seeders : Omitir la ejecución de seeders} {--force : Forzar sin confirmaciones}'; protected $description = 'Instala el sistema ANVALIA POS desde cero para un nuevo cliente'; private $steps = []; private $currentStep = 0; private $totalSteps = 0; public function handle() { $this->info(''); $this->info('╔══════════════════════════════════════════════════════════════╗'); $this->info('║ ANVALIA POS - INSTALACIÓN DEL SISTEMA ║'); $this->info('║ Sistema de Punto de Venta Multi-Tenant para Colombia ║'); $this->info('╚══════════════════════════════════════════════════════════════╝'); $this->info(''); // Verificar requisitos if (!$this->verificarRequisitos()) { return 1; } // Confirmar si es instalación fresh if ($this->option('fresh') && !$this->option('force')) { if (!$this->confirm('⚠️ ADVERTENCIA: --fresh eliminará TODOS los datos existentes. ¿Continuar?', false)) { $this->info('Instalación cancelada.'); return 0; } } // Definir pasos $this->definirPasos(); try { // Ejecutar cada paso foreach ($this->steps as $index => $step) { $this->currentStep = $index + 1; $this->ejecutarPaso($step); } $this->mostrarResumen(); return 0; } catch (\Exception $e) { $this->error(''); $this->error('❌ ERROR CRÍTICO: ' . $e->getMessage()); Log::error('Error en instalación del sistema', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return 1; } } private function verificarRequisitos(): bool { $this->info('🔍 Verificando requisitos del sistema...'); $this->info(''); $requisitos = [ 'PHP >= 8.1' => version_compare(PHP_VERSION, '8.1.0', '>='), 'Extensión PDO' => extension_loaded('pdo'), 'Extensión PDO MySQL' => extension_loaded('pdo_mysql'), 'Extensión OpenSSL' => extension_loaded('openssl'), 'Extensión Mbstring' => extension_loaded('mbstring'), 'Extensión Tokenizer' => extension_loaded('tokenizer'), 'Extensión XML' => extension_loaded('xml'), 'Extensión Ctype' => extension_loaded('ctype'), 'Extensión JSON' => extension_loaded('json'), 'Extensión BCMath' => extension_loaded('bcmath'), 'Extensión Fileinfo' => extension_loaded('fileinfo'), 'Extensión ZIP' => extension_loaded('zip'), ]; $todoOk = true; foreach ($requisitos as $nombre => $cumple) { if ($cumple) { $this->info(" ✅ {$nombre}"); } else { $this->error(" ❌ {$nombre}"); $todoOk = false; } } // Verificar conexión a base de datos $this->info(''); $this->info('🔍 Verificando conexión a base de datos...'); try { DB::connection()->getPdo(); $this->info(' ✅ Conexión a MySQL establecida'); $this->info(' 📍 Host: ' . config('database.connections.mysql.host')); $this->info(' 📍 Base de datos: ' . config('database.connections.mysql.database')); } catch (\Exception $e) { $this->error(' ❌ No se puede conectar a la base de datos'); $this->error(' ' . $e->getMessage()); $todoOk = false; } // Verificar mysqldump para backups $mysqldump = 'C:\\xampp\\mysql\\bin\\mysqldump.exe'; if (file_exists($mysqldump)) { $this->info(' ✅ mysqldump disponible para backups'); } else { $this->warn(' ⚠️ mysqldump no encontrado (backups pueden fallar)'); } $this->info(''); if (!$todoOk) { $this->error('❌ No se cumplen todos los requisitos. Por favor, corrija los errores antes de continuar.'); return false; } $this->info('✅ Todos los requisitos cumplidos'); $this->info(''); return true; } private function definirPasos(): void { $this->steps = []; // Paso 1: Crear backup de seguridad (si hay datos) if (!$this->option('fresh')) { $this->steps[] = [ 'nombre' => 'Crear backup de seguridad', 'metodo' => 'crearBackupSeguridad' ]; } // Paso 2: Limpiar cache $this->steps[] = [ 'nombre' => 'Limpiar cache del sistema', 'metodo' => 'limpiarCache' ]; // Paso 3: Ejecutar migraciones if ($this->option('fresh')) { $this->steps[] = [ 'nombre' => 'Ejecutar migraciones (fresh)', 'metodo' => 'ejecutarMigracionesFresh' ]; } else { $this->steps[] = [ 'nombre' => 'Ejecutar migraciones', 'metodo' => 'ejecutarMigraciones' ]; } // Paso 4: Ejecutar seeders (si no se omiten) if (!$this->option('skip-seeders')) { $this->steps[] = [ 'nombre' => 'Ejecutar seeders base', 'metodo' => 'ejecutarSeeders' ]; } // Paso 5: Configurar tenant (si se especifica) if ($this->option('tenant')) { $this->steps[] = [ 'nombre' => 'Configurar tenant específico', 'metodo' => 'configurarTenant' ]; } // Paso 6: Restaurar backup (si se proporciona) if ($this->option('backup')) { $this->steps[] = [ 'nombre' => 'Restaurar datos desde backup', 'metodo' => 'restaurarBackup' ]; } // Paso 7: Optimizar sistema $this->steps[] = [ 'nombre' => 'Optimizar sistema', 'metodo' => 'optimizarSistema' ]; // Paso 8: Verificar instalación $this->steps[] = [ 'nombre' => 'Verificar instalación', 'metodo' => 'verificarInstalacion' ]; $this->totalSteps = count($this->steps); } private function ejecutarPaso(array $paso): void { $this->info("📌 [{$this->currentStep}/{$this->totalSteps}] {$paso['nombre']}..."); $metodo = $paso['metodo']; $this->$metodo(); $this->info(" ✅ Completado"); $this->info(''); } private function crearBackupSeguridad(): void { try { $this->line(' Creando backup de seguridad antes de la instalación...'); Artisan::call('backup:database'); $output = Artisan::output(); $this->line(' ' . trim($output)); } catch (\Exception $e) { $this->warn(' ⚠️ No se pudo crear backup: ' . $e->getMessage()); } } private function limpiarCache(): void { $this->line(' Limpiando cache de configuración...'); Artisan::call('config:clear'); $this->line(' Limpiando cache de rutas...'); Artisan::call('route:clear'); $this->line(' Limpiando cache de vistas...'); Artisan::call('view:clear'); $this->line(' Limpiando cache de aplicación...'); Artisan::call('cache:clear'); } private function ejecutarMigracionesFresh(): void { $this->line(' Eliminando todas las tablas y ejecutando migraciones...'); Artisan::call('migrate:fresh', ['--force' => true]); $this->line(' ' . trim(Artisan::output())); // Migraciones de tenant $this->line(' Ejecutando migraciones de tenants...'); try { Artisan::call('tenants:migrate', ['--force' => true]); $this->line(' ' . trim(Artisan::output())); } catch (\Exception $e) { $this->warn(' ⚠️ Migraciones de tenant: ' . $e->getMessage()); } } private function ejecutarMigraciones(): void { $this->line(' Ejecutando migraciones pendientes...'); try { Artisan::call('migrate', ['--force' => true]); $output = trim(Artisan::output()); if (!empty($output)) { $this->line(' ' . $output); } $this->line(' ✓ Migraciones principales completadas'); } catch (\Exception $e) { // Si falla por tabla existente, continuar if (strpos($e->getMessage(), 'already exists') !== false) { $this->warn(' ⚠️ Algunas tablas ya existen, continuando...'); } else { throw $e; } } // Migraciones de tenant $this->line(' Ejecutando migraciones de tenants...'); try { Artisan::call('tenants:migrate', ['--force' => true]); $output = trim(Artisan::output()); if (!empty($output)) { $this->line(' ' . $output); } $this->line(' ✓ Migraciones de tenants completadas'); } catch (\Exception $e) { if (strpos($e->getMessage(), 'already exists') !== false) { $this->warn(' ⚠️ Algunas tablas de tenant ya existen, continuando...'); } else { $this->warn(' ⚠️ Migraciones de tenant: ' . substr($e->getMessage(), 0, 100)); } } } private function ejecutarSeeders(): void { $seeders = [ 'RolesPermisosSeeder' => 'Roles y permisos base', 'ActividadesSeeder' => 'Actividades del sistema', 'HotelNominaPermisosSeeder' => 'Permisos de Hotel y Nómina', 'ContabilidadPermisosSeeder' => 'Permisos de Contabilidad', ]; foreach ($seeders as $seeder => $descripcion) { $this->line(" Ejecutando {$descripcion}..."); try { // Intentar primero como seeder de tenant Artisan::call('tenants:seed', ['--class' => $seeder]); $this->line(' ✓ ' . $seeder); } catch (\Exception $e) { // Si falla, intentar como seeder normal try { Artisan::call('db:seed', ['--class' => $seeder, '--force' => true]); $this->line(' ✓ ' . $seeder); } catch (\Exception $e2) { $this->warn(" ⚠️ {$seeder}: " . $e2->getMessage()); } } } } private function configurarTenant(): void { $tenantId = $this->option('tenant'); $this->line(" Configurando tenant: {$tenantId}"); try { // Ejecutar migraciones específicas del tenant Artisan::call('tenants:migrate', [ '--tenants' => [$tenantId], '--force' => true ]); // Ejecutar seeders del tenant Artisan::call('tenants:seed', [ '--tenants' => [$tenantId], '--class' => 'ActividadesSeeder' ]); } catch (\Exception $e) { $this->warn(' ⚠️ Error configurando tenant: ' . $e->getMessage()); } } private function restaurarBackup(): void { $backupFile = $this->option('backup'); $backupPath = storage_path('app/backups/' . $backupFile); if (!File::exists($backupPath)) { // Intentar ruta absoluta if (File::exists($backupFile)) { $backupPath = $backupFile; } else { throw new \Exception("Archivo de backup no encontrado: {$backupFile}"); } } $this->line(" Restaurando desde: {$backupFile}"); $this->line(" Tamaño: " . $this->formatBytes(File::size($backupPath))); // Usar el comando de restauración mejorado Artisan::call('backup:restore-data-improved', [ 'file' => basename($backupPath), '--force' => true ]); $output = Artisan::output(); $this->line(' ' . str_replace("\n", "\n ", trim($output))); } private function optimizarSistema(): void { $this->line(' Generando cache de configuración...'); Artisan::call('config:cache'); $this->line(' Generando cache de rutas...'); try { Artisan::call('route:cache'); } catch (\Exception $e) { $this->warn(' ⚠️ Cache de rutas omitido (closures en rutas)'); } $this->line(' Generando cache de vistas...'); Artisan::call('view:cache'); $this->line(' Generando autoload optimizado...'); exec('composer dump-autoload --optimize 2>&1', $output, $returnCode); } private function verificarInstalacion(): void { $this->line(' Verificando tablas principales...'); $tablasRequeridas = [ 'users' => 'Usuarios', 'tenants' => 'Tenants', 'domains' => 'Dominios', 'roles' => 'Roles', 'permisos' => 'Permisos', 'actividades' => 'Actividades', ]; $tablasOpcionales = [ 'productos' => 'Productos', 'clientes' => 'Clientes', 'ventas' => 'Ventas', 'empresas' => 'Empresas', 'empleados' => 'Empleados (Nómina)', 'habitaciones' => 'Habitaciones (Hotel)', ]; foreach ($tablasRequeridas as $tabla => $nombre) { if (Schema::hasTable($tabla)) { $count = DB::table($tabla)->count(); $this->line(" ✅ {$nombre}: {$count} registros"); } else { $this->warn(" ⚠️ {$nombre}: tabla no existe"); } } $this->line(''); $this->line(' Tablas opcionales (módulos):'); foreach ($tablasOpcionales as $tabla => $nombre) { if (Schema::hasTable($tabla)) { $count = DB::table($tabla)->count(); $this->line(" ✅ {$nombre}: {$count} registros"); } else { $this->line(" ⬜ {$nombre}: no instalado"); } } } private function mostrarResumen(): void { $this->info(''); $this->info('╔══════════════════════════════════════════════════════════════╗'); $this->info('║ ✅ INSTALACIÓN COMPLETADA ║'); $this->info('╚══════════════════════════════════════════════════════════════╝'); $this->info(''); $this->info('📋 PRÓXIMOS PASOS:'); $this->info(''); $this->info(' 1. Configurar el archivo .env con los datos de la empresa'); $this->info(' 2. Crear el primer usuario administrador:'); $this->info(' php artisan tinker'); $this->info(' > App\\Models\\User::create([...])'); $this->info(''); $this->info(' 3. Acceder al sistema: http://localhost/ventas_completa/public'); $this->info(''); $this->info('📚 COMANDOS ÚTILES:'); $this->info(''); $this->info(' • Crear backup: php artisan backup:database'); $this->info(' • Restaurar backup: php artisan backup:restore-data-improved {archivo}'); $this->info(' • Ver backups: Acceder a /backup en el sistema'); $this->info(''); $this->info('🔧 SOPORTE:'); $this->info(' • Documentación: README.md'); $this->info(' • Logs: storage/logs/laravel.log'); $this->info(''); } private function formatBytes($bytes, $precision = 2): string { $units = ['B', 'KB', 'MB', 'GB', 'TB']; $bytes = max($bytes, 0); $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = min($pow, count($units) - 1); $bytes /= pow(1024, $pow); return round($bytes, $precision) . ' ' . $units[$pow]; } }
Coded With 💗 by
0x6ick