command->info(''); $this->command->info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); $this->command->info('🔧 경동기업 단가 테이블 마이그레이션 (kd_price_tables)'); $this->command->info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); // 기존 데이터 삭제 DB::table('kd_price_tables')->where('tenant_id', self::TENANT_ID)->delete(); $this->command->info(' → 기존 데이터 삭제 완료'); // chandj 연결 가능 여부 확인 $chandjAvailable = $this->checkChandjConnection(); if ($chandjAvailable) { $this->command->info(' → chandj 데이터베이스 연결됨'); $this->migrateFromChandj(); } else { $this->command->warn(' → chandj 데이터베이스 연결 불가 - 샘플 데이터 사용'); $this->insertSampleData(); } $count = DB::table('kd_price_tables')->where('tenant_id', self::TENANT_ID)->count(); $this->command->info(''); $this->command->info("✅ 완료: kd_price_tables {$count}건"); } /** * chandj 데이터베이스 연결 확인 */ private function checkChandjConnection(): bool { try { DB::connection('chandj')->getPdo(); return true; } catch (\Exception $e) { return false; } } /** * chandj 데이터베이스에서 마이그레이션 */ private function migrateFromChandj(): void { $this->migrateMotorPrices(); $this->migrateShaftPrices(); $this->migratePipePrices(); $this->migrateAnglePrices(); $this->migrateRawMaterialPrices(); } /** * price_motor → kd_price_tables */ private function migrateMotorPrices(): void { $this->command->info(''); $this->command->info('📦 [1/5] price_motor 마이그레이션...'); $priceMotor = DB::connection('chandj') ->table('price_motor') ->where(function ($q) { $q->where('is_deleted', 0)->orWhereNull('is_deleted'); }) ->orderByDesc('registedate') ->first(); if (! $priceMotor || empty($priceMotor->itemList)) { $this->command->info(' → 데이터 없음'); return; } $itemList = json_decode($priceMotor->itemList, true); if (! is_array($itemList)) { $this->command->info(' → JSON 파싱 실패'); return; } $count = 0; $now = now(); foreach ($itemList as $item) { $col1 = $item['col1'] ?? ''; // 전압/카테고리 (220, 380, 제어기 등) $col2 = $item['col2'] ?? ''; // 용량/품목명 $salesPrice = (float) str_replace(',', '', $item['col13'] ?? '0'); if (empty($col2) || $salesPrice <= 0) { continue; } // 카테고리 결정 $category = match ($col1) { '220', '380' => $col2, // 모터 용량 (150K, 300K 등) default => $col1, // 제어기, 방화, 방범 등 }; KdPriceTable::create([ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_MOTOR, 'item_name' => trim("{$col1} {$col2}"), 'category' => $category, 'spec1' => $col1, 'spec2' => $col2, 'unit_price' => $salesPrice, 'unit' => 'EA', 'raw_data' => $item, 'is_active' => true, ]); $count++; } $this->command->info(" → {$count}건 완료"); } /** * price_shaft → kd_price_tables */ private function migrateShaftPrices(): void { $this->command->info(''); $this->command->info('📦 [2/5] price_shaft 마이그레이션...'); $priceShaft = DB::connection('chandj') ->table('price_shaft') ->where(function ($q) { $q->where('is_deleted', 0)->orWhereNull('is_deleted'); }) ->orderByDesc('registedate') ->first(); if (! $priceShaft || empty($priceShaft->itemList)) { $this->command->info(' → 데이터 없음'); return; } $itemList = json_decode($priceShaft->itemList, true); if (! is_array($itemList)) { $this->command->info(' → JSON 파싱 실패'); return; } $count = 0; foreach ($itemList as $item) { $size = $item['col4'] ?? ''; // 사이즈 (3, 4, 5인치) $length = $item['col10'] ?? ''; // 길이 (m 단위) $salesPrice = (float) str_replace(',', '', $item['col19'] ?? '0'); if (empty($size) || $salesPrice <= 0) { continue; } KdPriceTable::create([ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_SHAFT, 'item_name' => "감기샤프트 {$size}인치 {$length}m", 'category' => '감기샤프트', 'spec1' => $size, 'spec2' => $length, 'unit_price' => $salesPrice, 'unit' => 'EA', 'raw_data' => $item, 'is_active' => true, ]); $count++; } $this->command->info(" → {$count}건 완료"); } /** * price_pipe → kd_price_tables */ private function migratePipePrices(): void { $this->command->info(''); $this->command->info('📦 [3/5] price_pipe 마이그레이션...'); $pricePipe = DB::connection('chandj') ->table('price_pipe') ->where(function ($q) { $q->where('is_deleted', 0)->orWhereNull('is_deleted'); }) ->orderByDesc('registedate') ->first(); if (! $pricePipe || empty($pricePipe->itemList)) { $this->command->info(' → 데이터 없음'); return; } $itemList = json_decode($pricePipe->itemList, true); if (! is_array($itemList)) { $this->command->info(' → JSON 파싱 실패'); return; } $count = 0; foreach ($itemList as $item) { $length = $item['col2'] ?? ''; // 길이 (3000, 6000) $thickness = $item['col4'] ?? ''; // 두께 (1.4) $salesPrice = (float) str_replace(',', '', $item['col8'] ?? '0'); if (empty($thickness) || $salesPrice <= 0) { continue; } KdPriceTable::create([ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_PIPE, 'item_name' => "각파이프 {$thickness}T {$length}mm", 'category' => '각파이프', 'spec1' => $thickness, 'spec2' => $length, 'unit_price' => $salesPrice, 'unit' => 'EA', 'raw_data' => $item, 'is_active' => true, ]); $count++; } $this->command->info(" → {$count}건 완료"); } /** * price_angle → kd_price_tables */ private function migrateAnglePrices(): void { $this->command->info(''); $this->command->info('📦 [4/5] price_angle 마이그레이션...'); $priceAngle = DB::connection('chandj') ->table('price_angle') ->where(function ($q) { $q->where('is_deleted', 0)->orWhereNull('is_deleted'); }) ->orderByDesc('registedate') ->first(); if (! $priceAngle || empty($priceAngle->itemList)) { $this->command->info(' → 데이터 없음'); return; } $itemList = json_decode($priceAngle->itemList, true); if (! is_array($itemList)) { $this->command->info(' → JSON 파싱 실패'); return; } $count = 0; foreach ($itemList as $item) { $type = $item['col2'] ?? ''; // 타입 (스크린용, 철재용) $bracketSize = $item['col3'] ?? ''; // 브라켓크기 $angleType = $item['col4'] ?? ''; // 앵글타입 (앵글3T, 앵글4T) $thickness = $item['col10'] ?? ''; // 두께 $salesPrice = (float) str_replace(',', '', $item['col19'] ?? '0'); if (empty($type) || $salesPrice <= 0) { continue; } KdPriceTable::create([ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_ANGLE, 'item_name' => "앵글 {$type} {$bracketSize} {$angleType}", 'category' => $type, 'spec1' => $bracketSize, 'spec2' => $angleType, 'spec3' => $thickness, 'unit_price' => $salesPrice, 'unit' => 'EA', 'raw_data' => $item, 'is_active' => true, ]); $count++; } $this->command->info(" → {$count}건 완료"); } /** * price_raw_materials → kd_price_tables */ private function migrateRawMaterialPrices(): void { $this->command->info(''); $this->command->info('📦 [5/5] price_raw_materials 마이그레이션...'); $priceRaw = DB::connection('chandj') ->table('price_raw_materials') ->where(function ($q) { $q->where('is_deleted', 0)->orWhereNull('is_deleted'); }) ->orderByDesc('registedate') ->first(); if (! $priceRaw || empty($priceRaw->itemList)) { $this->command->info(' → 데이터 없음'); return; } $itemList = json_decode($priceRaw->itemList, true); if (! is_array($itemList)) { $this->command->info(' → JSON 파싱 실패'); return; } $count = 0; foreach ($itemList as $item) { $name = $item['col2'] ?? ''; $spec = $item['col3'] ?? ''; $salesPrice = (float) str_replace(',', '', $item['col19'] ?? $item['col13'] ?? '0'); if (empty($name) || $salesPrice <= 0) { continue; } KdPriceTable::create([ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_RAW_MATERIAL, 'item_name' => $name, 'category' => '원자재', 'spec1' => $spec, 'unit_price' => $salesPrice, 'unit' => '㎡', 'raw_data' => $item, 'is_active' => true, ]); $count++; } $this->command->info(" → {$count}건 완료"); } /** * chandj 연결 불가 시 샘플 데이터 삽입 */ private function insertSampleData(): void { $this->command->info(''); $this->command->info('📦 샘플 데이터 삽입 중...'); // 모터 샘플 데이터 (5130 분석 결과 기반) $motorData = [ ['category' => '150K', 'spec1' => '220', 'spec2' => '150K', 'unit_price' => 85000], ['category' => '300K', 'spec1' => '220', 'spec2' => '300K', 'unit_price' => 120000], ['category' => '400K', 'spec1' => '220', 'spec2' => '400K', 'unit_price' => 150000], ['category' => '500K', 'spec1' => '220', 'spec2' => '500K', 'unit_price' => 180000], ['category' => '600K', 'spec1' => '220', 'spec2' => '600K', 'unit_price' => 220000], ['category' => '800K', 'spec1' => '220', 'spec2' => '800K', 'unit_price' => 280000], ['category' => '1000K', 'spec1' => '220', 'spec2' => '1000K', 'unit_price' => 350000], ['category' => '매립형', 'spec1' => '제어기', 'spec2' => '매립형', 'unit_price' => 45000], ['category' => '노출형', 'spec1' => '제어기', 'spec2' => '노출형', 'unit_price' => 55000], ['category' => '뒷박스', 'spec1' => '제어기', 'spec2' => '뒷박스', 'unit_price' => 35000], ]; foreach ($motorData as $data) { KdPriceTable::create(array_merge($data, [ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_MOTOR, 'item_name' => "모터/제어기 {$data['category']}", 'unit' => 'EA', 'is_active' => true, ])); } $this->command->info(' → 모터/제어기 '.count($motorData).'건'); // 샤프트 샘플 데이터 $shaftData = [ ['spec1' => '3', 'spec2' => '3.0', 'unit_price' => 45000], ['spec1' => '4', 'spec2' => '3.0', 'unit_price' => 55000], ['spec1' => '5', 'spec2' => '3.0', 'unit_price' => 65000], ['spec1' => '3', 'spec2' => '4.0', 'unit_price' => 60000], ['spec1' => '4', 'spec2' => '4.0', 'unit_price' => 75000], ['spec1' => '5', 'spec2' => '4.0', 'unit_price' => 90000], ]; foreach ($shaftData as $data) { KdPriceTable::create(array_merge($data, [ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_SHAFT, 'item_name' => "감기샤프트 {$data['spec1']}인치 {$data['spec2']}m", 'category' => '감기샤프트', 'unit' => 'EA', 'is_active' => true, ])); } $this->command->info(' → 샤프트 '.count($shaftData).'건'); // 파이프 샘플 데이터 $pipeData = [ ['spec1' => '1.4', 'spec2' => '3000', 'unit_price' => 12000], ['spec1' => '1.4', 'spec2' => '6000', 'unit_price' => 24000], ]; foreach ($pipeData as $data) { KdPriceTable::create(array_merge($data, [ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_PIPE, 'item_name' => "각파이프 {$data['spec1']}T {$data['spec2']}mm", 'category' => '각파이프', 'unit' => 'EA', 'is_active' => true, ])); } $this->command->info(' → 파이프 '.count($pipeData).'건'); // 앵글 샘플 데이터 $angleData = [ ['category' => '스크린용', 'spec1' => '530*320', 'spec2' => '앵글3T', 'unit_price' => 8000], ['category' => '스크린용', 'spec1' => '600*350', 'spec2' => '앵글3T', 'unit_price' => 10000], ['category' => '스크린용', 'spec1' => '690*390', 'spec2' => '앵글4T', 'unit_price' => 12000], ['category' => '철재용', 'spec1' => '530*320', 'spec2' => '앵글3T', 'unit_price' => 9000], ['category' => '철재용', 'spec1' => '600*350', 'spec2' => '앵글3T', 'unit_price' => 11000], ['category' => '철재용', 'spec1' => '690*390', 'spec2' => '앵글4T', 'unit_price' => 14000], ]; foreach ($angleData as $data) { KdPriceTable::create(array_merge($data, [ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_ANGLE, 'item_name' => "앵글 {$data['category']} {$data['spec1']} {$data['spec2']}", 'unit' => 'EA', 'is_active' => true, ])); } $this->command->info(' → 앵글 '.count($angleData).'건'); // 원자재 샘플 데이터 $rawData = [ ['item_name' => '실리카', 'spec1' => '스크린용', 'unit_price' => 25000], ['item_name' => '불투명', 'spec1' => '스크린용', 'unit_price' => 22000], ['item_name' => '화이바원단', 'spec1' => '스크린용', 'unit_price' => 28000], ]; foreach ($rawData as $data) { KdPriceTable::create(array_merge($data, [ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_RAW_MATERIAL, 'category' => '원자재', 'unit' => '㎡', 'is_active' => true, ])); } $this->command->info(' → 원자재 '.count($rawData).'건'); // BDmodels 샘플 데이터 (절곡품) $this->insertBDModelsSampleData(); } /** * BDmodels 샘플 데이터 삽입 (절곡품) */ private function insertBDModelsSampleData(): void { $bdmodelsData = [ // 케이스 (규격별 단가 - 원/m) ['category' => '케이스', 'spec2' => '500*380', 'unit_price' => 15000, 'unit' => 'm'], ['category' => '케이스', 'spec2' => '550*430', 'unit_price' => 18000, 'unit' => 'm'], ['category' => '케이스', 'spec2' => '650*550', 'unit_price' => 22000, 'unit' => 'm'], // 케이스 마구리 (규격별 단가 - 원/개) ['category' => '마구리', 'spec2' => '500*380', 'unit_price' => 5000, 'unit' => 'EA'], ['category' => '마구리', 'spec2' => '550*430', 'unit_price' => 6000, 'unit' => 'EA'], ['category' => '마구리', 'spec2' => '650*550', 'unit_price' => 7500, 'unit' => 'EA'], // 케이스용 연기차단재 (공통 단가 - 원/m) ['category' => '케이스용 연기차단재', 'unit_price' => 3500, 'unit' => 'm'], // 가이드레일 (모델+마감+규격별 단가 - 원/m) ['category' => '가이드레일', 'item_code' => 'KSS01', 'spec1' => 'SUS', 'spec2' => '120*70', 'unit_price' => 12000, 'unit' => 'm'], ['category' => '가이드레일', 'item_code' => 'KSS01', 'spec1' => 'SUS', 'spec2' => '120*100', 'unit_price' => 15000, 'unit' => 'm'], ['category' => '가이드레일', 'item_code' => 'KSS01', 'spec1' => 'EGI', 'spec2' => '120*70', 'unit_price' => 10000, 'unit' => 'm'], ['category' => '가이드레일', 'item_code' => 'KSS01', 'spec1' => 'EGI', 'spec2' => '120*100', 'unit_price' => 13000, 'unit' => 'm'], ['category' => '가이드레일', 'item_code' => 'KWS01', 'spec1' => 'SUS', 'spec2' => '120*70', 'unit_price' => 13000, 'unit' => 'm'], ['category' => '가이드레일', 'item_code' => 'KWS01', 'spec1' => 'SUS', 'spec2' => '120*100', 'unit_price' => 16000, 'unit' => 'm'], // 가이드레일용 연기차단재 (공통 단가 - 원/m) ['category' => '가이드레일용 연기차단재', 'unit_price' => 2500, 'unit' => 'm'], // 하단마감재/하장바 (모델+마감별 단가 - 원/m) ['category' => '하단마감재', 'item_code' => 'KSS01', 'spec1' => 'SUS', 'unit_price' => 8000, 'unit' => 'm'], ['category' => '하단마감재', 'item_code' => 'KSS01', 'spec1' => 'EGI', 'unit_price' => 6500, 'unit' => 'm'], ['category' => '하단마감재', 'item_code' => 'KWS01', 'spec1' => 'SUS', 'unit_price' => 8500, 'unit' => 'm'], // L-BAR (모델별 단가 - 원/m) ['category' => 'L-BAR', 'item_code' => 'KSS01', 'unit_price' => 4500, 'unit' => 'm'], ['category' => 'L-BAR', 'item_code' => 'KWS01', 'unit_price' => 5000, 'unit' => 'm'], // 보강평철 (공통 단가 - 원/m) ['category' => '보강평철', 'unit_price' => 3000, 'unit' => 'm'], ]; foreach ($bdmodelsData as $data) { $itemCode = $data['item_code'] ?? null; $spec1 = $data['spec1'] ?? null; $spec2 = $data['spec2'] ?? null; $itemName = $data['category']; if ($itemCode) { $itemName .= " {$itemCode}"; } if ($spec1) { $itemName .= " {$spec1}"; } if ($spec2) { $itemName .= " {$spec2}"; } KdPriceTable::create([ 'tenant_id' => self::TENANT_ID, 'table_type' => KdPriceTable::TYPE_BDMODELS, 'item_code' => $itemCode, 'item_name' => $itemName, 'category' => $data['category'], 'spec1' => $spec1, 'spec2' => $spec2, 'unit_price' => $data['unit_price'], 'unit' => $data['unit'], 'is_active' => true, ]); } $this->command->info(' → BDmodels(절곡품) '.count($bdmodelsData).'건'); } }