Files
sam-api/app/Console/Commands/BendingImportImages.php
강영보 c29090a0b8 feat: [bending] 절곡품 전용 테이블 분리 API
- bending_items 전용 테이블 생성 (items.options → 정규 컬럼 승격)
- bending_models 전용 테이블 생성 (가이드레일/케이스/하단마감재 통합)
- bending_data JSON 통합 (별도 테이블 → bending_items.bending_data 컬럼)
- bending_item_mappings 테이블 DROP (bending_items.code에 흡수)
- BendingItemService/BendingCodeService → BendingItem 모델 전환
- GuiderailModelService component 이미지 자동 복사
- ItemsFileController bending_items/bending_models 폴백 지원
- Swagger 스키마 업데이트
2026-03-19 20:00:18 +09:00

116 lines
3.9 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\BendingItem;
use App\Models\Commons\File;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
/**
* 레거시 이미지 → R2 업로드 + bending_items 연결
*
* 실행: php artisan bending:import-images [--dry-run] [--tenant_id=287]
*/
class BendingImportImages extends Command
{
protected $signature = 'bending:import-images
{--tenant_id=287 : 테넌트 ID}
{--dry-run : 미리보기}
{--legacy-path=/home/kkk/sam/5130/bending/img : 레거시 이미지 경로}';
protected $description = '레거시 절곡품 이미지 → R2 업로드 + bending_items 연결';
public function handle(): int
{
$tenantId = (int) $this->option('tenant_id');
$dryRun = $this->option('dry-run');
$legacyPath = $this->option('legacy-path');
$items = BendingItem::where('tenant_id', $tenantId)
->whereNotNull('legacy_bending_id')
->get();
$chandjMap = DB::connection('chandj')->table('bending')
->whereNotNull('imgdata')
->where('imgdata', '!=', '')
->pluck('imgdata', 'num');
$this->info("bending_items: {$items->count()}건 / chandj imgdata: {$chandjMap->count()}");
$uploaded = 0;
$skipped = 0;
$notFound = 0;
$errors = 0;
foreach ($items as $bi) {
$imgFile = $chandjMap[$bi->legacy_bending_id] ?? null;
if (! $imgFile) {
$skipped++;
continue;
}
$filePath = "{$legacyPath}/{$imgFile}";
if (! file_exists($filePath)) {
$this->warn(" ⚠️ 파일 없음: {$imgFile} (#{$bi->legacy_bending_id})");
$notFound++;
continue;
}
$existing = File::where('document_type', 'bending_item')
->where('document_id', $bi->id)
->where('field_key', 'bending_diagram')
->whereNull('deleted_at')
->first();
if ($existing) {
$skipped++;
continue;
}
if ($dryRun) {
$this->line(" [DRY] #{$bi->legacy_bending_id}{$bi->id} ({$bi->item_name}) ← {$imgFile}");
$uploaded++;
continue;
}
try {
$extension = pathinfo($imgFile, PATHINFO_EXTENSION);
$storedName = bin2hex(random_bytes(8)) . '.' . $extension;
$directory = sprintf('%d/bending/%s/%s', $tenantId, date('Y'), date('m'));
$r2Path = $directory . '/' . $storedName;
Storage::disk('r2')->put($r2Path, file_get_contents($filePath));
File::create([
'tenant_id' => $tenantId,
'display_name' => $imgFile,
'stored_name' => $storedName,
'file_path' => $r2Path,
'file_size' => filesize($filePath),
'mime_type' => mime_content_type($filePath),
'file_type' => 'image',
'field_key' => 'bending_diagram',
'document_id' => $bi->id,
'document_type' => 'bending_item',
'is_temp' => false,
'uploaded_by' => 1,
'created_by' => 1,
]);
$this->line(" ✅ #{$bi->legacy_bending_id}{$bi->id} ({$bi->item_name}) ← {$imgFile}");
$uploaded++;
} catch (\Throwable $e) {
$this->error(" ❌ #{$bi->legacy_bending_id}: {$e->getMessage()}");
$errors++;
}
}
$this->newLine();
$this->info("완료: 업로드 {$uploaded}, 스킵 {$skipped}, 파일없음 {$notFound}, 오류 {$errors}");
return 0;
}
}