Files
sam-api/scripts/register-bending-items.php
김보곤 6af9162ce4 feat: [bending] 절곡품 품목 일괄 등록 + LOT 매핑 (222건 신규)
- BendingCodeService에 42(4200mm) 길이코드 복원
- 품목 일괄 등록 스크립트 추가 (scripts/register-bending-items.php)
- 신규 종류(RW/RF/SW/SF/TE/GH) + 신규 길이(06/17/20/45) 조합 등록
- bending_item_mappings 320건 매핑 동시 등록
2026-03-18 19:43:15 +09:00

171 lines
8.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 절곡품 품목 일괄 등록 + bending_item_mappings 매핑
*
* 실행: docker exec sam-api-1 php artisan tinker < scripts/register-bending-items.php
*
* - LOT 채번 규칙 기준 누락 품목 자동 생성
* - 기존 품목은 건너뜀 (코드 중복 방지)
* - bending_item_mappings에 매핑 동시 등록
*/
$tenantId = 287; // 경동기업
// =========================================================================
// 1. 조합 정의 (제품코드+종류코드 → 메타데이터)
// =========================================================================
$combos = [
// 가이드레일(벽면형) R
'RM' => ['prod' => 'R', 'spec' => 'M', 'label' => '가이드레일(벽면) 본체', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'RT' => ['prod' => 'R', 'spec' => 'T', 'label' => '가이드레일(벽면) 본체(철재)', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'RC' => ['prod' => 'R', 'spec' => 'C', 'label' => '가이드레일(벽면) C형', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'RD' => ['prod' => 'R', 'spec' => 'D', 'label' => '가이드레일(벽면) D형', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'RS' => ['prod' => 'R', 'spec' => 'S', 'label' => '가이드레일(벽면) SUS마감재', 'bending' => '가이드레일', 'material' => 'SUS 1.2T'],
'RW' => ['prod' => 'R', 'spec' => 'W', 'label' => '가이드레일(벽면) 본체(L120)', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'RF' => ['prod' => 'R', 'spec' => 'F', 'label' => '가이드레일(벽면) SUS마감재(L120)', 'bending' => '가이드레일', 'material' => 'SUS 1.2T'],
// 가이드레일(측면형) S
'SM' => ['prod' => 'S', 'spec' => 'M', 'label' => '가이드레일(측면) 본체디딤', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'ST' => ['prod' => 'S', 'spec' => 'T', 'label' => '가이드레일(측면) 본체(철재)', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'SC' => ['prod' => 'S', 'spec' => 'C', 'label' => '가이드레일(측면) C형', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'SD' => ['prod' => 'S', 'spec' => 'D', 'label' => '가이드레일(측면) D형', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'SS' => ['prod' => 'S', 'spec' => 'S', 'label' => '가이드레일(측면) SUS마감재(3)', 'bending' => '가이드레일', 'material' => 'SUS 1.2T'],
'SU' => ['prod' => 'S', 'spec' => 'U', 'label' => '가이드레일(측면) SUS마감재(3)', 'bending' => '가이드레일', 'material' => 'SUS 1.2T'],
'SW' => ['prod' => 'S', 'spec' => 'W', 'label' => '가이드레일(측면) 본체(L120)', 'bending' => '가이드레일', 'material' => 'EGI 1.55T'],
'SF' => ['prod' => 'S', 'spec' => 'F', 'label' => '가이드레일(측면) SUS마감재(L120)', 'bending' => '가이드레일', 'material' => 'SUS 1.2T'],
// 케이스 C
'CF' => ['prod' => 'C', 'spec' => 'F', 'label' => '케이스 전면부', 'bending' => '케이스', 'material' => 'EGI 1.55T'],
'CP' => ['prod' => 'C', 'spec' => 'P', 'label' => '케이스 점검구', 'bending' => '케이스', 'material' => 'EGI 1.55T'],
'CL' => ['prod' => 'C', 'spec' => 'L', 'label' => '케이스 린텔부', 'bending' => '케이스', 'material' => 'EGI 1.55T'],
'CB' => ['prod' => 'C', 'spec' => 'B', 'label' => '케이스 후면코너부', 'bending' => '케이스', 'material' => 'EGI 1.55T'],
// 하단마감재
'BS' => ['prod' => 'B', 'spec' => 'S', 'label' => '하단마감재(스크린) SUS', 'bending' => '하단마감재', 'material' => 'SUS 1.2T'],
'BE' => ['prod' => 'B', 'spec' => 'E', 'label' => '하단마감재(스크린) EGI', 'bending' => '하단마감재', 'material' => 'EGI 1.55T'],
'TS' => ['prod' => 'T', 'spec' => 'S', 'label' => '하단마감재(철재) SUS', 'bending' => '하단마감재', 'material' => 'SUS 1.2T'],
'TE' => ['prod' => 'T', 'spec' => 'E', 'label' => '하단마감재(철재) EGI', 'bending' => '하단마감재', 'material' => 'EGI 1.55T'],
// L-Bar
'LA' => ['prod' => 'L', 'spec' => 'A', 'label' => 'L-Bar 스크린용', 'bending' => 'L-BAR', 'material' => 'EGI 1.55T'],
// 연기차단재
'GI' => ['prod' => 'G', 'spec' => 'I', 'label' => '연기차단재 화이바원단(W50)', 'bending' => '연기차단재', 'material' => '화이바원단', 'type' => 'both'],
'GH' => ['prod' => 'G', 'spec' => 'H', 'label' => '연기차단재 화이바원단(W80)', 'bending' => '연기차단재', 'material' => '화이바원단', 'type' => 'both'],
];
// =========================================================================
// 2. 길이 코드 정의
// =========================================================================
$generalLengths = [
'06' => '610mm', '12' => '1219mm', '17' => '1750mm', '20' => '2000mm',
'24' => '2438mm', '30' => '3000mm', '35' => '3500mm', '40' => '4000mm',
'41' => '4150mm', '42' => '4200mm', '43' => '4300mm', '45' => '4500mm',
];
$smokeLengths = [
'53' => 'W50×3000', '54' => 'W50×4000',
'83' => 'W80×3000', '84' => 'W80×4000',
];
// =========================================================================
// 3. 기존 품목 조회
// =========================================================================
$existingCodes = DB::table('items')
->where('tenant_id', $tenantId)
->where('item_category', 'BENDING')
->whereNull('deleted_at')
->pluck('id', 'code')
->toArray();
echo "기존 BENDING 품목: " . count($existingCodes) . "\n\n";
// =========================================================================
// 4. 누락 품목 생성
// =========================================================================
$created = 0;
$skipped = 0;
$mappingCreated = 0;
$now = now();
DB::beginTransaction();
try {
foreach ($combos as $comboKey => $meta) {
// 길이 목록 결정 (+ 연산자로 문자열 키 보존 — array_merge는 숫자형 키 재번호)
$type = $meta['type'] ?? 'general';
if ($type === 'both') {
$lengths = $generalLengths + $smokeLengths;
} elseif ($type === 'smoke') {
$lengths = $smokeLengths;
} else {
$lengths = $generalLengths;
}
foreach ($lengths as $lenCode => $lenName) {
$code = "BD-{$comboKey}-{$lenCode}";
$name = "{$meta['label']} {$lenName}";
// 이미 존재하면 매핑만 확인
if (isset($existingCodes[$code])) {
$itemId = $existingCodes[$code];
$skipped++;
} else {
// 품목 생성
$itemId = DB::table('items')->insertGetId([
'tenant_id' => $tenantId,
'item_type' => 'PT',
'code' => $code,
'name' => $name,
'unit' => 'EA',
'item_category' => 'BENDING',
'is_active' => true,
'options' => json_encode([
'item_bending' => $meta['bending'],
'material' => $meta['material'],
]),
'created_at' => $now,
'updated_at' => $now,
]);
$created++;
echo "{$code} | {$name}\n";
}
// bending_item_mappings 등록 (중복 방지)
$mappingExists = DB::table('bending_item_mappings')
->where('tenant_id', $tenantId)
->where('prod_code', $meta['prod'])
->where('spec_code', $meta['spec'])
->where('length_code', $lenCode)
->exists();
if (! $mappingExists) {
DB::table('bending_item_mappings')->insert([
'tenant_id' => $tenantId,
'prod_code' => $meta['prod'],
'spec_code' => $meta['spec'],
'length_code' => $lenCode,
'item_id' => $itemId,
'is_active' => true,
'created_at' => $now,
'updated_at' => $now,
]);
$mappingCreated++;
}
}
}
DB::commit();
echo "\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
echo " 품목 신규 생성: {$created}\n";
echo " 품목 기존 유지: {$skipped}\n";
echo " 매핑 등록: {$mappingCreated}\n";
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
} catch (\Exception $e) {
DB::rollBack();
echo "\n❌ 오류 발생: " . $e->getMessage() . "\n";
echo "롤백 완료\n";
}