option('tenant_id'); $dryRun = $this->option('dry-run'); $this->info('=== chandj guiderail → SAM 임포트 ==='); $this->info('Mode: '.($dryRun ? 'DRY-RUN' : 'LIVE')); $rows = DB::connection('chandj')->table('guiderail')->whereNull('is_deleted')->get(); $this->info("chandj guiderail: {$rows->count()}건"); $created = 0; $skipped = 0; foreach ($rows as $row) { $finish = str_contains($row->finishing_type ?? '', 'SUS') ? 'SUS' : 'EGI'; $code = 'GR-'.($row->model_name ?? 'UNKNOWN').'-'.($row->check_type ?? '').'-'.$finish; $name = implode(' ', array_filter([$row->model_name, $row->check_type, $row->finishing_type])); // 중복 확인 $existing = DB::table('items') ->where('tenant_id', $tenantId) ->where('code', $code) ->whereNull('deleted_at') ->first(); if ($existing) { $skipped++; continue; } // components 변환 $legacyComps = json_decode($row->bending_components ?? '[]', true) ?: []; $components = array_map(fn ($c) => $this->convertComponent($c), $legacyComps); $materialSummary = json_decode($row->material_summary ?? '{}', true) ?: []; $options = [ 'model_name' => $row->model_name, 'check_type' => $row->check_type, 'rail_width' => (int) $row->rail_width, 'rail_length' => (int) $row->rail_length, 'finishing_type' => $row->finishing_type, 'item_sep' => $row->firstitem, 'model_UA' => $row->model_UA, 'search_keyword' => $row->search_keyword, 'author' => $row->author, 'registration_date' => $row->registration_date, 'memo' => $row->remark, 'components' => $components, 'material_summary' => $materialSummary, 'source' => 'chandj_guiderail', 'legacy_guiderail_num' => $row->num, ]; if (! $dryRun) { DB::table('items')->insert([ 'tenant_id' => $tenantId, 'code' => $code, 'name' => $name, 'item_type' => 'FG', 'item_category' => 'GUIDERAIL_MODEL', 'unit' => 'SET', 'options' => json_encode($options, JSON_UNESCAPED_UNICODE), 'is_active' => true, 'created_at' => now(), 'updated_at' => now(), ]); } $created++; $this->line(" ✅ {$code} ({$name}) — {$row->firstitem}/{$row->model_UA} — 부품 ".count($components).'개'); } $this->newLine(); $this->info("생성: {$created}건 | 스킵(중복): {$skipped}건"); if ($dryRun) { $this->info('🔍 DRY-RUN 완료.'); } return self::SUCCESS; } private function convertComponent(array $c): array { $inputs = $c['inputList'] ?? []; $rates = $c['bendingrateList'] ?? []; $sums = $c['sumList'] ?? []; $colors = $c['colorList'] ?? []; $angles = $c['AList'] ?? []; // bendingData 형식으로 변환 $bendingData = []; for ($i = 0; $i < count($inputs); $i++) { $bendingData[] = [ 'no' => $i + 1, 'input' => (float) ($inputs[$i] ?? 0), 'rate' => (string) ($rates[$i] ?? ''), 'sum' => (float) ($sums[$i] ?? 0), 'color' => (bool) ($colors[$i] ?? false), 'aAngle' => (bool) ($angles[$i] ?? false), ]; } $lastSum = ! empty($sums) ? (float) end($sums) : 0; return [ 'orderNumber' => $c['orderNumber'] ?? null, 'itemName' => $c['itemName'] ?? '', 'material' => $c['material'] ?? '', 'quantity' => (int) ($c['quantity'] ?? 1), 'width_sum' => $lastSum, 'bendingData' => $bendingData, 'legacy_bending_num' => $c['num'] ?? null, ]; } }