refactor: 절곡 재고 마이그레이션 커맨드 리팩토링 및 검증/시더 추가

- Migrate5130BendingStock: BD-* 품목 초기 재고 셋팅으로 목적 변경, --min-stock 옵션 추가
- ValidateBendingItems: BD-* 품목 존재 여부 검증 커맨드 신규
- BendingItemSeeder: 경동 절곡 품목 시딩 신규

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 03:04:47 +09:00
parent b00fa0502a
commit 855e806e42
3 changed files with 642 additions and 496 deletions

View File

@@ -0,0 +1,151 @@
<?php
namespace Database\Seeders\Kyungdong;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
/**
* BD-* 미등록 절곡 세부품목 일괄 등록
*
* Phase 0.1: BD-XX (7개), BD-YY (4개), BD-HH (2개)
* 추가 누락: BD-RM/RC/RD-42, BD-SM-24, BD-BS-35/43, BD-TS-43, BD-GI-54/84
*
* 실행: php artisan db:seed --class="Database\Seeders\Kyungdong\BendingItemSeeder"
*/
class BendingItemSeeder extends Seeder
{
private int $tenantId = 287; // 경동기업
/**
* 길이코드 → mm 매핑
*/
private const LENGTH_MAP = [
'12' => 1219,
'24' => 2438,
'30' => 3000,
'35' => 3500,
'40' => 4000,
'41' => 4150,
'42' => 4200,
'43' => 4300,
'53' => 3000, // 연기차단재50 전용
'54' => 4000, // 연기차단재50 전용
'83' => 3000, // 연기차단재80 전용
'84' => 4000, // 연기차단재80 전용
];
/**
* 등록 대상 정의
*/
private function getItemDefinitions(): array
{
return [
// Phase 0.1 대상
'XX' => [
'name' => '하부BASE/셔터 상부/마구리',
'lengthCodes' => ['12', '24', '30', '35', '40', '41', '43'],
],
'YY' => [
'name' => '별도SUS마감',
'lengthCodes' => ['30', '35', '40', '43'],
],
'HH' => [
'name' => '보강평철',
'lengthCodes' => ['30', '40'],
],
// 추가 누락분
'RM' => [
'name' => '가이드레일(벽면) 본체',
'lengthCodes' => ['42'],
],
'RC' => [
'name' => '가이드레일(벽면) C형',
'lengthCodes' => ['42'],
],
'RD' => [
'name' => '가이드레일(벽면) D형',
'lengthCodes' => ['42'],
],
'SM' => [
'name' => '가이드레일(측면) 본체',
'lengthCodes' => ['24'],
],
'BS' => [
'name' => '하단마감재 SUS',
'lengthCodes' => ['35', '43'],
],
'TS' => [
'name' => '하단마감재 철재SUS',
'lengthCodes' => ['43'],
],
'GI' => [
'name' => '연기차단재',
'lengthCodes' => ['54', '84'],
'nameOverrides' => [
'54' => '연기차단재 W50 4000mm',
'84' => '연기차단재 W80 4000mm',
],
],
];
}
public function run(): void
{
$definitions = $this->getItemDefinitions();
$created = 0;
$skipped = 0;
foreach ($definitions as $prefix => $def) {
foreach ($def['lengthCodes'] as $lengthCode) {
$code = "BD-{$prefix}-{$lengthCode}";
$lengthMm = self::LENGTH_MAP[$lengthCode];
$name = ($def['nameOverrides'][$lengthCode] ?? null)
?: "{$def['name']} {$lengthMm}mm";
$exists = DB::table('items')
->where('tenant_id', $this->tenantId)
->where('code', $code)
->whereNull('deleted_at')
->exists();
if ($exists) {
$this->command?->line(" ⏭️ skip (exists): {$code}");
$skipped++;
continue;
}
DB::table('items')->insert([
'tenant_id' => $this->tenantId,
'code' => $code,
'name' => $name,
'item_type' => 'PT',
'item_category' => 'BENDING',
'unit' => 'EA',
'bom' => null,
'attributes' => json_encode([]),
'attributes_archive' => json_encode([]),
'options' => json_encode([
'source' => 'bending_item_seeder',
'lot_managed' => true,
'consumption_method' => 'auto',
'production_source' => 'self_produced',
'input_tracking' => true,
'prefix' => $prefix,
'length_code' => $lengthCode,
'length_mm' => $lengthMm,
]),
'is_active' => true,
'created_at' => now(),
'updated_at' => now(),
]);
$this->command?->line(" ✅ created: {$code} ({$name})");
$created++;
}
}
$this->command?->info("BD-* 누락 품목 등록 완료: 생성 {$created}건, 스킵 {$skipped}");
}
}