feat: 경동기업 품목/단가 마이그레이션 Seeder 구현 (Phase 1.0)
- KyungdongItemSeeder.php 생성 - chandj.KDunitprice → samdb.items, prices 마이그레이션 - is_deleted=NULL 조건 반영 (레거시 데이터 특성) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
221
database/seeders/Kyungdong/KyungdongItemSeeder.php
Normal file
221
database/seeders/Kyungdong/KyungdongItemSeeder.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Kyungdong;
|
||||
|
||||
use Database\Seeders\DummyDataSeeder;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 경동기업 품목/단가 마이그레이션 Seeder
|
||||
*
|
||||
* 소스: chandj.KDunitprice (603건)
|
||||
* 타겟: samdb.items, samdb.prices
|
||||
*
|
||||
* @see docs/plans/kd-items-migration-plan.md
|
||||
*/
|
||||
class KyungdongItemSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* item_div → item_type 매핑
|
||||
*/
|
||||
private const ITEM_TYPE_MAP = [
|
||||
'[제품]' => 'FG',
|
||||
'[상품]' => 'FG',
|
||||
'[반제품]' => 'PT',
|
||||
'[부재료]' => 'SM',
|
||||
'[원재료]' => 'RM',
|
||||
'[무형상품]' => 'CS',
|
||||
];
|
||||
|
||||
/**
|
||||
* 경동기업 품목/단가 마이그레이션 실행
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$tenantId = DummyDataSeeder::TENANT_ID;
|
||||
$userId = DummyDataSeeder::USER_ID;
|
||||
|
||||
$this->command->info('🚀 경동기업 품목/단가 마이그레이션 시작...');
|
||||
$this->command->info(" 대상 테넌트: ID {$tenantId}");
|
||||
|
||||
// 1. 기존 데이터 삭제
|
||||
$this->cleanupExistingData($tenantId);
|
||||
|
||||
// 2. KDunitprice → items
|
||||
$itemCount = $this->migrateItems($tenantId, $userId);
|
||||
|
||||
// 3. items 기반 → prices
|
||||
$priceCount = $this->migratePrices($tenantId, $userId);
|
||||
|
||||
$this->command->info('');
|
||||
$this->command->info("✅ 마이그레이션 완료: items {$itemCount}건, prices {$priceCount}건");
|
||||
}
|
||||
|
||||
/**
|
||||
* 기존 데이터 삭제 (tenant_id 기준)
|
||||
*/
|
||||
private function cleanupExistingData(int $tenantId): void
|
||||
{
|
||||
$this->command->info('');
|
||||
$this->command->info('🧹 기존 데이터 삭제 중...');
|
||||
|
||||
// prices 먼저 삭제 (FK 관계)
|
||||
$priceCount = DB::table('prices')->where('tenant_id', $tenantId)->count();
|
||||
DB::table('prices')->where('tenant_id', $tenantId)->delete();
|
||||
$this->command->info(" → prices: {$priceCount}건 삭제");
|
||||
|
||||
// items 삭제
|
||||
$itemCount = DB::table('items')->where('tenant_id', $tenantId)->count();
|
||||
DB::table('items')->where('tenant_id', $tenantId)->delete();
|
||||
$this->command->info(" → items: {$itemCount}건 삭제");
|
||||
}
|
||||
|
||||
/**
|
||||
* KDunitprice → items 마이그레이션
|
||||
*/
|
||||
private function migrateItems(int $tenantId, int $userId): int
|
||||
{
|
||||
$this->command->info('');
|
||||
$this->command->info('📦 KDunitprice → items 마이그레이션...');
|
||||
|
||||
// chandj.KDunitprice에서 데이터 조회 (is_deleted=NULL이 활성 상태)
|
||||
$kdItems = DB::connection('chandj')
|
||||
->table('KDunitprice')
|
||||
->whereNull('is_deleted')
|
||||
->whereNotNull('prodcode')
|
||||
->where('prodcode', '!=', '')
|
||||
->get();
|
||||
|
||||
$this->command->info(" → 소스 데이터: {$kdItems->count()}건");
|
||||
|
||||
$items = [];
|
||||
$now = now();
|
||||
$batchCount = 0;
|
||||
|
||||
foreach ($kdItems as $kd) {
|
||||
$items[] = [
|
||||
'tenant_id' => $tenantId,
|
||||
'item_type' => $this->mapItemType($kd->item_div),
|
||||
'code' => $kd->prodcode,
|
||||
'name' => $kd->item_name,
|
||||
'unit' => $kd->unit,
|
||||
'category_id' => null,
|
||||
'process_type' => null,
|
||||
'item_category' => null,
|
||||
'bom' => null,
|
||||
'attributes' => json_encode([
|
||||
'spec' => $kd->spec,
|
||||
'item_div' => $kd->item_div,
|
||||
'legacy_source' => 'KDunitprice',
|
||||
'legacy_num' => $kd->num,
|
||||
]),
|
||||
'attributes_archive' => null,
|
||||
'options' => null,
|
||||
'description' => null,
|
||||
'is_active' => true,
|
||||
'created_by' => $userId,
|
||||
'updated_by' => $userId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
// 500건씩 배치 INSERT
|
||||
if (count($items) >= 500) {
|
||||
DB::table('items')->insert($items);
|
||||
$batchCount += count($items);
|
||||
$this->command->info(" → {$batchCount}건 완료...");
|
||||
$items = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 남은 데이터 INSERT
|
||||
if (! empty($items)) {
|
||||
DB::table('items')->insert($items);
|
||||
$batchCount += count($items);
|
||||
}
|
||||
|
||||
$this->command->info(" ✓ items: {$batchCount}건 생성 완료");
|
||||
|
||||
return $batchCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* items 기반 → prices 마이그레이션
|
||||
*/
|
||||
private function migratePrices(int $tenantId, int $userId): int
|
||||
{
|
||||
$this->command->info('');
|
||||
$this->command->info('💰 items → prices 마이그레이션...');
|
||||
|
||||
// 생성된 items와 KDunitprice 조인하여 prices 생성
|
||||
$items = DB::table('items')
|
||||
->where('tenant_id', $tenantId)
|
||||
->get(['id', 'code', 'item_type']);
|
||||
|
||||
$kdPrices = DB::connection('chandj')
|
||||
->table('KDunitprice')
|
||||
->whereNull('is_deleted')
|
||||
->whereNotNull('prodcode')
|
||||
->where('prodcode', '!=', '')
|
||||
->pluck('unitprice', 'prodcode');
|
||||
|
||||
$prices = [];
|
||||
$now = now();
|
||||
$batchCount = 0;
|
||||
|
||||
foreach ($items as $item) {
|
||||
$unitPrice = $kdPrices[$item->code] ?? 0;
|
||||
|
||||
$prices[] = [
|
||||
'tenant_id' => $tenantId,
|
||||
'item_type_code' => $item->item_type,
|
||||
'item_id' => $item->id,
|
||||
'client_group_id' => null,
|
||||
'purchase_price' => 0,
|
||||
'processing_cost' => null,
|
||||
'loss_rate' => null,
|
||||
'margin_rate' => null,
|
||||
'sales_price' => $unitPrice,
|
||||
'rounding_rule' => 'round',
|
||||
'rounding_unit' => 1,
|
||||
'supplier' => null,
|
||||
'effective_from' => now()->toDateString(),
|
||||
'effective_to' => null,
|
||||
'note' => 'KDunitprice 마이그레이션',
|
||||
'status' => 'active',
|
||||
'is_final' => false,
|
||||
'created_by' => $userId,
|
||||
'updated_by' => $userId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
// 500건씩 배치 INSERT
|
||||
if (count($prices) >= 500) {
|
||||
DB::table('prices')->insert($prices);
|
||||
$batchCount += count($prices);
|
||||
$this->command->info(" → {$batchCount}건 완료...");
|
||||
$prices = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 남은 데이터 INSERT
|
||||
if (! empty($prices)) {
|
||||
DB::table('prices')->insert($prices);
|
||||
$batchCount += count($prices);
|
||||
}
|
||||
|
||||
$this->command->info(" ✓ prices: {$batchCount}건 생성 완료");
|
||||
|
||||
return $batchCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* item_div → item_type 매핑
|
||||
*/
|
||||
private function mapItemType(?string $itemDiv): string
|
||||
{
|
||||
return self::ITEM_TYPE_MAP[$itemDiv] ?? 'SM';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user