info("Iniciando importación del Excel con lógica de proveedores..."); // Aseguramos que existan al menos los 3 proveedores básicos por si acaso $this->asegurarProveedores(); $rutaCompleta = storage_path('app/imports/catalogo_limpio.csv'); if (!file_exists($rutaCompleta)) { $this->error("No se encontró el archivo en: " . $rutaCompleta); return; } $file = fopen($rutaCompleta, 'r'); fgetcsv($file); // Saltar cabecera $contador = 0; while (($fila = fgetcsv($file, 1000, ',')) !== false) { // 1. Lectura de las 6 columnas $tipoRaw = strtolower(trim($fila[0] ?? '')); $nombreRaw = trim($fila[1] ?? ''); $descripcionRaw = trim($fila[2] ?? ''); $costoRaw = trim($fila[3] ?? ''); $precioRaw = trim($fila[4] ?? ''); $proveedorId = trim($fila[5] ?? 1); // ID del proveedor if (empty($nombreRaw)) continue; // 2. Limpieza de Nombre (Primera letra de cada palabra) $nombreSinEspacios = preg_replace('/\s+/', ' ', $nombreRaw); $nombreFinal = mb_convert_case($nombreSinEspacios, MB_CASE_TITLE, "UTF-8"); // 3. Traductor de Categorías (Evita errores SQL de truncado) $tipoRaw = preg_replace('/[\xEF\xBB\xBF]/', '', $tipoRaw); // Limpieza de BOM $mapeoTipos = [ 'bicicleta' => 'bike', 'bicicletas' => 'bike', 'bike' => 'bike', 'indumentaria' => 'clothing', 'ropa' => 'clothing', 'clothing' => 'clothing', 'accesorio' => 'accessory', 'accesorios' => 'accessory', 'accessory' => 'accessory', 'repuesto' => 'spare', 'repuestos' => 'spare', 'spare' => 'spare', 'infantil' => 'children', 'niños' => 'children', 'children' => 'children', 'rollers' => 'rollers', 'roller' => 'rollers', 'skate' => 'skate', 'skates' => 'skate', 'servicio' => 'service', 'service' => 'service', 'otro' => 'other', 'otros' => 'other', 'other' => 'other' ]; $tipoFinal = $mapeoTipos[$tipoRaw] ?? 'other'; // 4. Limpieza de Precios $costoLimpio = (float) str_replace(['$', ' ', ','], '', $costoRaw); $precioLimpio = (float) str_replace(['$', ' ', ','], '', $precioRaw); // 5. Creación o Actualización Product::withTrashed()->updateOrCreate( ['name' => $nombreFinal], [ 'description' => $descripcionRaw, 'type' => $tipoFinal, 'cost' => $costoLimpio, 'price' => $precioLimpio, 'suppliers_id' => $proveedorId, 'stock_quantity' => 20, 'min_stock_alert' => 5, 'deleted_at' => null, ] ); $contador++; } fclose($file); $this->info("¡Éxito! Se procesaron {$contador} productos con sus respectivos proveedores."); } private function asegurarProveedores() { $proveedores = [ 1 => 'Proveedor General Lauck', 2 => 'Distribuidora Norte', 3 => 'Repuestos Express' ]; foreach ($proveedores as $id => $name) { Supplier::withTrashed()->firstOrCreate( ['id' => $id], [ 'name' => $name, 'phone' => '0000000000', 'deleted_at' => null ] ); } } }