option('tenant_id'); $dryRun = $this->option('dry-run'); $legacyPath = $this->option('legacy-path'); $items = BendingItem::where('tenant_id', $tenantId) ->whereNotNull('legacy_bending_id') ->get(); $chandjMap = DB::connection('chandj')->table('bending') ->whereNotNull('imgdata') ->where('imgdata', '!=', '') ->pluck('imgdata', 'num'); $this->info("bending_items: {$items->count()}건 / chandj imgdata: {$chandjMap->count()}건"); $uploaded = 0; $skipped = 0; $notFound = 0; $errors = 0; foreach ($items as $bi) { $imgFile = $chandjMap[$bi->legacy_bending_id] ?? null; if (! $imgFile) { $skipped++; continue; } $filePath = "{$legacyPath}/{$imgFile}"; if (! file_exists($filePath)) { $this->warn(" ⚠️ 파일 없음: {$imgFile} (#{$bi->legacy_bending_id})"); $notFound++; continue; } $existing = File::where('document_type', 'bending_item') ->where('document_id', $bi->id) ->where('field_key', 'bending_diagram') ->whereNull('deleted_at') ->first(); if ($existing) { $skipped++; continue; } if ($dryRun) { $this->line(" [DRY] #{$bi->legacy_bending_id} → {$bi->id} ({$bi->item_name}) ← {$imgFile}"); $uploaded++; continue; } try { $extension = pathinfo($imgFile, PATHINFO_EXTENSION); $storedName = bin2hex(random_bytes(8)) . '.' . $extension; $directory = sprintf('%d/bending/%s/%s', $tenantId, date('Y'), date('m')); $r2Path = $directory . '/' . $storedName; Storage::disk('r2')->put($r2Path, file_get_contents($filePath)); File::create([ 'tenant_id' => $tenantId, 'display_name' => $imgFile, 'stored_name' => $storedName, 'file_path' => $r2Path, 'file_size' => filesize($filePath), 'mime_type' => mime_content_type($filePath), 'file_type' => 'image', 'field_key' => 'bending_diagram', 'document_id' => $bi->id, 'document_type' => 'bending_item', 'is_temp' => false, 'uploaded_by' => 1, 'created_by' => 1, ]); $this->line(" ✅ #{$bi->legacy_bending_id} → {$bi->id} ({$bi->item_name}) ← {$imgFile}"); $uploaded++; } catch (\Throwable $e) { $this->error(" ❌ #{$bi->legacy_bending_id}: {$e->getMessage()}"); $errors++; } } $this->newLine(); $this->info("완료: 업로드 {$uploaded}, 스킵 {$skipped}, 파일없음 {$notFound}, 오류 {$errors}"); return 0; } }