diff --git a/database/migrations/2026_03_21_210000_fix_bending_item_codes.php b/database/migrations/2026_03_21_210000_fix_bending_item_codes.php new file mode 100644 index 00000000..899c6e0f --- /dev/null +++ b/database/migrations/2026_03_21_210000_fix_bending_item_codes.php @@ -0,0 +1,154 @@ +whereNull('deleted_at') + ->orderBy('id') + ->get(['id', 'item_name', 'item_bending', 'material', 'item_sep']); + + // 접두사별 카운터 + $counters = []; + + foreach ($items as $item) { + $prefix = $this->classify($item); + + if (! isset($counters[$prefix])) { + $counters[$prefix] = 0; + } + $counters[$prefix]++; + $seq = str_pad($counters[$prefix], 3, '0', STR_PAD_LEFT); + + DB::table('bending_items') + ->where('id', $item->id) + ->update(['code' => "BD-{$prefix}.{$seq}"]); + } + } + + public function down(): void + { + // 롤백 시 원래 'BD'로 복원 (원래 상태가 전부 BD였으므로) + DB::table('bending_items') + ->whereNull('deleted_at') + ->update(['code' => 'BD']); + } + + private function classify(object $item): string + { + $name = $item->item_name ?? ''; + $bending = $item->item_bending ?? ''; + $material = $item->material ?? ''; + $sep = $item->item_sep ?? ''; + + // L-BAR + if ($bending === 'L-BAR') { + return 'LE'; + } + + // 마구리 + if ($bending === '마구리') { + return 'XE'; + } + + // 하단마감재 + if ($bending === '하단마감재') { + if (str_contains($name, '보강평철')) { + return 'BH'; + } + if ($sep === '철재') { + return str_contains($material, 'SUS') ? 'TS' : 'TE'; + } + // 스크린 + return str_contains($material, 'SUS') ? 'BS' : 'BE'; + } + + // 케이스 + if ($bending === '케이스') { + if (str_contains($name, '전면')) { + return 'CF'; + } + if (str_contains($name, '린텔')) { + return 'CL'; + } + if (str_contains($name, '상부') || str_contains($name, '덮개')) { + return 'CX'; + } + if (str_contains($name, '밑면') || str_contains($name, '하부') || str_contains($name, '점검구')) { + return 'CP'; + } + if (str_contains($name, '후면')) { + return 'CB'; + } + + return 'CF'; // fallback + } + + // 가이드레일 + if ($bending === '가이드레일') { + if (str_contains($name, '비인정')) { + return 'RN'; + } + if (str_contains($name, '뒷보강')) { + return 'RH'; + } + if (str_contains($name, '절단판')) { + return 'RT'; + } + // C형/D형 — '-C', 'C형', 'C각', '벽면형-C', '측면형-C' 등 (문자열 끝 포함) + if (preg_match('/[-\(]C(?:[^a-zA-Z가-힣]|$)|C형|C각/u', $name)) { + return 'RC'; + } + if (preg_match('/[-\(]D(?:[^a-zA-Z가-힣]|$)|D형/u', $name)) { + return 'RD'; + } + // SUS 재질 → SUS마감재 + if (str_contains($material, 'SUS')) { + return 'RS'; + } + // 본체/보강 + if (str_contains($name, '본체') || str_contains($name, '보강')) { + return 'RM'; + } + // 측면 마감 + if (str_contains($name, '측면')) { + return 'RE'; + } + // EGI 마감재 → 측면마감 카테고리 + if (str_contains($name, '마감')) { + return 'RE'; + } + + return 'RM'; // fallback + } + + // item_bending이 NULL인 특수 부품 + if (empty($bending)) { + if (str_contains($name, '전면')) { + return 'ZF'; + } + if (str_contains($name, '밑면') || str_contains($name, '점검구')) { + return 'ZP'; + } + if (str_contains($name, '후면')) { + return 'ZB'; + } + + return 'ZF'; // fallback + } + + return 'XX'; // unknown + } +};