feat: 경동기업 품목 기준 데이터 배포용 시더 구현
- ExportItemMasterDataCommand: tenant_id=287 데이터를 JSON으로 추출 - KyungdongItemMasterSeeder: JSON 기반 DELETE+재삽입 시더 - Phase 1: item_pages/sections/fields + entity_relationships - Phase 2: categories(depth순) + items(배치500건) - Phase 3: item_details + prices - ID 매핑으로 환경별 충돌 없음, 트랜잭션 안전 - 8개 JSON 데이터 파일 포함 (총 약 1.5MB) - .gitignore에 시더 데이터 예외 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
202
app/Console/Commands/ExportItemMasterDataCommand.php
Normal file
202
app/Console/Commands/ExportItemMasterDataCommand.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 경동기업(tenant_id=287) 품목 기준 데이터를 JSON으로 추출
|
||||
*
|
||||
* 추출 대상: item_pages, item_sections, item_fields,
|
||||
* entity_relationships, categories, items, item_details, prices
|
||||
*
|
||||
* 사용법: php artisan kyungdong:export-item-master
|
||||
*/
|
||||
class ExportItemMasterDataCommand extends Command
|
||||
{
|
||||
protected $signature = 'kyungdong:export-item-master';
|
||||
|
||||
protected $description = '경동기업(tenant_id=287) 품목 기준 데이터를 JSON 파일로 추출';
|
||||
|
||||
private const TENANT_ID = 287;
|
||||
|
||||
private string $outputPath;
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$this->outputPath = database_path('seeders/data/kyungdong');
|
||||
|
||||
if (! is_dir($this->outputPath)) {
|
||||
mkdir($this->outputPath, 0755, true);
|
||||
}
|
||||
|
||||
$this->info('경동기업 품목 기준 데이터 추출 시작 (tenant_id=' . self::TENANT_ID . ')');
|
||||
$this->newLine();
|
||||
|
||||
$this->exportItemPages();
|
||||
$this->exportItemSections();
|
||||
$this->exportItemFields();
|
||||
$this->exportEntityRelationships();
|
||||
$this->exportCategories();
|
||||
$this->exportItems();
|
||||
$this->exportItemDetails();
|
||||
$this->exportPrices();
|
||||
|
||||
$this->newLine();
|
||||
$this->info('추출 완료! 경로: ' . $this->outputPath);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function exportItemPages(): void
|
||||
{
|
||||
$rows = DB::table('item_pages')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->whereNull('deleted_at')
|
||||
->get()
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('item_pages.json', $rows);
|
||||
$this->info(" item_pages: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
private function exportItemSections(): void
|
||||
{
|
||||
$rows = DB::table('item_sections')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->whereNull('deleted_at')
|
||||
->get()
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('item_sections.json', $rows);
|
||||
$this->info(" item_sections: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
private function exportItemFields(): void
|
||||
{
|
||||
$rows = DB::table('item_fields')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->whereNull('deleted_at')
|
||||
->get()
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('item_fields.json', $rows);
|
||||
$this->info(" item_fields: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
private function exportEntityRelationships(): void
|
||||
{
|
||||
// 참조 대상이 실제 존재하는 것만 추출
|
||||
$validPageIds = DB::table('item_pages')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');
|
||||
$validSectionIds = DB::table('item_sections')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');
|
||||
$validFieldIds = DB::table('item_fields')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');
|
||||
$validBomIds = DB::table('item_bom_items')->where('tenant_id', self::TENANT_ID)->whereNull('deleted_at')->pluck('id');
|
||||
|
||||
$validIds = [
|
||||
'page' => $validPageIds->flip(),
|
||||
'section' => $validSectionIds->flip(),
|
||||
'field' => $validFieldIds->flip(),
|
||||
'bom' => $validBomIds->flip(),
|
||||
];
|
||||
|
||||
$rows = DB::table('entity_relationships')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->get()
|
||||
->filter(function ($row) use ($validIds) {
|
||||
$parentValid = isset($validIds[$row->parent_type][$row->parent_id]);
|
||||
$childValid = isset($validIds[$row->child_type][$row->child_id]);
|
||||
|
||||
return $parentValid && $childValid;
|
||||
})
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('entity_relationships.json', $rows);
|
||||
$this->info(" entity_relationships: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
private function exportCategories(): void
|
||||
{
|
||||
$rows = DB::table('categories')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->whereNull('deleted_at')
|
||||
->orderByRaw('COALESCE(parent_id, 0), sort_order, id')
|
||||
->get()
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('categories.json', $rows);
|
||||
$this->info(" categories: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
private function exportItems(): void
|
||||
{
|
||||
$rows = DB::table('items')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->whereNull('deleted_at')
|
||||
->orderBy('id')
|
||||
->get()
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('items.json', $rows);
|
||||
$this->info(" items: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
private function exportItemDetails(): void
|
||||
{
|
||||
$itemIds = DB::table('items')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->whereNull('deleted_at')
|
||||
->pluck('id');
|
||||
|
||||
$rows = DB::table('item_details')
|
||||
->whereIn('item_id', $itemIds)
|
||||
->get()
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('item_details.json', $rows);
|
||||
$this->info(" item_details: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
private function exportPrices(): void
|
||||
{
|
||||
$rows = DB::table('prices')
|
||||
->where('tenant_id', self::TENANT_ID)
|
||||
->whereNull('deleted_at')
|
||||
->orderBy('id')
|
||||
->get()
|
||||
->map(fn ($row) => $this->addOriginalId($row))
|
||||
->toArray();
|
||||
|
||||
$this->writeJson('prices.json', $rows);
|
||||
$this->info(" prices: " . count($rows) . "건");
|
||||
}
|
||||
|
||||
/**
|
||||
* _original_id 추가 + id 제거
|
||||
*/
|
||||
private function addOriginalId(object $row): array
|
||||
{
|
||||
$data = (array) $row;
|
||||
$data['_original_id'] = $data['id'];
|
||||
unset($data['id']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function writeJson(string $filename, array $data): void
|
||||
{
|
||||
$path = $this->outputPath . '/' . $filename;
|
||||
file_put_contents(
|
||||
$path,
|
||||
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user