option('tenant_id'); $dryRun = $this->option('dry-run'); $this->info('=== sam_item_id 일괄 매핑 ==='); $this->info('Mode: ' . ($dryRun ? 'DRY-RUN' : 'LIVE')); // 1. legacy_bending_num → SAM item ID 매핑 테이블 구축 $bendingItems = Item::withoutGlobalScopes() ->where('tenant_id', $tenantId) ->where('item_category', 'BENDING') ->whereNull('deleted_at') ->get(); $legacyMap = []; foreach ($bendingItems as $item) { $legacyNum = $item->getOption('legacy_bending_num'); if ($legacyNum !== null) { $legacyMap[(string) $legacyNum] = $item->id; } } $this->info("BENDING items: {$bendingItems->count()}건, legacy_bending_num 매핑: " . count($legacyMap) . '건'); // 2. 모델 items의 components 순회 $models = Item::withoutGlobalScopes() ->where('tenant_id', $tenantId) ->whereIn('item_category', ['GUIDERAIL_MODEL', 'SHUTTERBOX_MODEL', 'BOTTOMBAR_MODEL']) ->whereNull('deleted_at') ->get(); $this->info("모델: {$models->count()}건"); $updated = 0; $mapped = 0; $notFound = 0; foreach ($models as $model) { $components = $model->getOption('components', []); if (empty($components)) { continue; } $changed = false; foreach ($components as &$comp) { // 이미 sam_item_id가 있으면 스킵 if (! empty($comp['sam_item_id'])) { continue; } $legacyNum = $comp['legacy_bending_num'] ?? null; if ($legacyNum === null) { continue; } $samId = $legacyMap[(string) $legacyNum] ?? null; if ($samId) { $comp['sam_item_id'] = $samId; $changed = true; $mapped++; } else { $notFound++; $this->warn(" [{$model->id}] legacy_bending_num={$legacyNum} → SAM ID 없음 ({$comp['itemName']})"); } } unset($comp); if ($changed && ! $dryRun) { $model->setOption('components', $components); $model->save(); $updated++; } elseif ($changed) { $updated++; } } $this->info(''); $this->info("결과: 모델 {$updated}건 업데이트, 컴포넌트 {$mapped}건 매핑, {$notFound}건 미매핑"); return self::SUCCESS; } }