refactor: 절곡 재고 마이그레이션 커맨드 리팩토링 및 검증/시더 추가
- Migrate5130BendingStock: BD-* 품목 초기 재고 셋팅으로 목적 변경, --min-stock 옵션 추가 - ValidateBendingItems: BD-* 품목 존재 여부 검증 커맨드 신규 - BendingItemSeeder: 경동 절곡 품목 시딩 신규 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
137
app/Console/Commands/ValidateBendingItems.php
Normal file
137
app/Console/Commands/ValidateBendingItems.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Attributes\AsCommand;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
#[AsCommand(name: 'bending:validate-items', description: 'BD-* 절곡 세부품목 마스터 데이터 검증 (prefix × lengthCode 전 조합)')]
|
||||
class ValidateBendingItems extends Command
|
||||
{
|
||||
protected $signature = 'bending:validate-items
|
||||
{--tenant_id=287 : Target tenant ID (default: 287 경동기업)}';
|
||||
|
||||
/**
|
||||
* prefix별 유효 길이코드 정의
|
||||
*
|
||||
* 가이드레일: 30, 35, 40, 43 (벽면/측면 공통)
|
||||
* 하단마감재: 30, 40
|
||||
* 셔터박스: 12, 24, 30, 35, 40, 41
|
||||
* 연기차단재: 53, 54, 83, 84 (W50/W80 전용 코드)
|
||||
* XX: 12, 24, 30, 35, 40, 41, 43 (하부BASE + 셔터 상부/마구리)
|
||||
* YY: 30, 35, 40, 43 (별도 SUS 마감)
|
||||
* HH: 30, 40 (보강평철)
|
||||
*/
|
||||
private function getPrefixLengthCodes(): array
|
||||
{
|
||||
$guideRailCodes = ['30', '35', '40', '43'];
|
||||
$guideRailCodesWithExtra = ['24', '30', '35', '40', '43']; // RT/ST는 적은 종류
|
||||
$bottomBarCodes = ['30', '40'];
|
||||
$shutterBoxCodes = ['12', '24', '30', '35', '40', '41'];
|
||||
|
||||
return [
|
||||
// 가이드레일 벽면형
|
||||
'RS' => $guideRailCodes, // 벽면 SUS 마감재
|
||||
'RM' => ['24', '30', '35', '40', '42', '43'], // 벽면 본체 (EGI)
|
||||
'RC' => ['24', '30', '35', '40', '42', '43'], // 벽면 C형
|
||||
'RD' => ['24', '30', '35', '40', '42', '43'], // 벽면 D형
|
||||
'RT' => ['30', '43'], // 벽면 본체 (철재)
|
||||
|
||||
// 가이드레일 측면형
|
||||
'SS' => ['30', '35', '40'], // 측면 SUS 마감재
|
||||
'SM' => ['24', '30', '35', '40', '43'], // 측면 본체 (EGI)
|
||||
'SC' => ['24', '30', '35', '40', '43'], // 측면 C형
|
||||
'SD' => ['24', '30', '35', '40', '43'], // 측면 D형
|
||||
'ST' => ['43'], // 측면 본체 (철재)
|
||||
'SU' => ['30', '35', '40', '43'], // 측면 SUS (SUS2)
|
||||
|
||||
// 하단마감재
|
||||
'BE' => $bottomBarCodes, // EGI 마감
|
||||
'BS' => ['24', '30', '35', '40', '43'], // SUS 마감
|
||||
'TS' => ['43'], // 철재 SUS
|
||||
'LA' => $bottomBarCodes, // L-Bar
|
||||
|
||||
// 셔터박스
|
||||
'CF' => $shutterBoxCodes, // 전면부
|
||||
'CL' => $shutterBoxCodes, // 린텔부
|
||||
'CP' => $shutterBoxCodes, // 점검구
|
||||
'CB' => $shutterBoxCodes, // 후면코너부
|
||||
|
||||
// 연기차단재
|
||||
'GI' => ['53', '54', '83', '84', '30', '35', '40'], // W50/W80 + 일반
|
||||
|
||||
// 공용/기타
|
||||
'XX' => ['12', '24', '30', '35', '40', '41', '43'], // 하부BASE/셔터 상부/마구리
|
||||
'YY' => ['30', '35', '40', '43'], // 별도 SUS 마감
|
||||
'HH' => ['30', '40'], // 보강평철
|
||||
];
|
||||
}
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$tenantId = (int) $this->option('tenant_id');
|
||||
|
||||
$this->info("=== BD-* 절곡 세부품목 마스터 검증 (tenant: {$tenantId}) ===");
|
||||
$this->newLine();
|
||||
|
||||
// DB에서 전체 BD-* 품목 조회
|
||||
$existingItems = DB::table('items')
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', 'like', 'BD-%')
|
||||
->whereNull('deleted_at')
|
||||
->pluck('code')
|
||||
->toArray();
|
||||
|
||||
$existingSet = array_flip($existingItems);
|
||||
|
||||
$this->info('현재 등록된 BD-* 품목: '.count($existingItems).'개');
|
||||
$this->newLine();
|
||||
|
||||
$prefixMap = $this->getPrefixLengthCodes();
|
||||
$totalExpected = 0;
|
||||
$missing = [];
|
||||
$found = 0;
|
||||
|
||||
foreach ($prefixMap as $prefix => $codes) {
|
||||
$prefixMissing = [];
|
||||
foreach ($codes as $code) {
|
||||
$itemCode = "BD-{$prefix}-{$code}";
|
||||
$totalExpected++;
|
||||
|
||||
if (isset($existingSet[$itemCode])) {
|
||||
$found++;
|
||||
} else {
|
||||
$prefixMissing[] = $itemCode;
|
||||
$missing[] = $itemCode;
|
||||
}
|
||||
}
|
||||
|
||||
$status = empty($prefixMissing) ? '✅' : '❌';
|
||||
$countStr = count($codes) - count($prefixMissing).'/'.count($codes);
|
||||
$this->line(" {$status} BD-{$prefix}: {$countStr}");
|
||||
|
||||
if (! empty($prefixMissing)) {
|
||||
foreach ($prefixMissing as $m) {
|
||||
$this->line(" ⚠️ 누락: {$m}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->newLine();
|
||||
$this->info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||||
$this->info("검증 결과: {$found}/{$totalExpected} 등록 완료");
|
||||
|
||||
if (empty($missing)) {
|
||||
$this->info('✅ All items registered — 누락 0건');
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$this->warn('❌ 누락 항목: '.count($missing).'건');
|
||||
$this->newLine();
|
||||
$this->table(['누락 품목코드'], array_map(fn ($m) => [$m], $missing));
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user