feat: ItemMaster 데이터베이스 구조 구축 (9개 테이블)
- 마이그레이션 9개 생성 (unit_options, section_templates, item_master_fields, item_pages, item_sections, item_fields, item_bom_items, custom_tabs, tab_columns) - Eloquent 모델 9개 구현 (ItemMaster 네임스페이스) - ItemMasterSeeder 작성 및 테스트 데이터 생성 주요 특징: - Multi-tenant 지원 (BelongsToTenant trait) - Soft Delete 적용 (deleted_at, deleted_by) - 감사 로그 지원 (created_by, updated_by) - JSON 필드로 동적 속성 지원 (display_condition, validation_rules, options, properties) - FK 제약조건 및 Composite Index 설정 - 계층 구조 (ItemPage → ItemSection → ItemField/ItemBomItem) SAM API Development Rules 준수
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('unit_options', function (Blueprint $table) {
|
||||
$table->id()->comment('단위 옵션 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->string('label', 100)->comment('단위 라벨');
|
||||
$table->string('value', 50)->comment('단위 값');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index('tenant_id', 'idx_unit_options_tenant_id');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_unit_options_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('unit_options');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('section_templates', function (Blueprint $table) {
|
||||
$table->id()->comment('섹션 템플릿 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->string('title')->comment('템플릿명');
|
||||
$table->enum('type', ['fields', 'bom'])->default('fields')->comment('섹션 타입 (fields: 필드형, bom: BOM형)');
|
||||
$table->text('description')->nullable()->comment('설명');
|
||||
$table->boolean('is_default')->default(false)->comment('기본 템플릿 여부');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index('tenant_id', 'idx_section_templates_tenant_id');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_section_templates_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('section_templates');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('item_master_fields', function (Blueprint $table) {
|
||||
$table->id()->comment('마스터 필드 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->string('field_name')->comment('필드명');
|
||||
$table->enum('field_type', ['textbox', 'number', 'dropdown', 'checkbox', 'date', 'textarea'])->comment('필드 타입');
|
||||
$table->string('category', 100)->nullable()->comment('카테고리');
|
||||
$table->text('description')->nullable()->comment('설명');
|
||||
$table->boolean('is_common')->default(false)->comment('공통 필드 여부');
|
||||
$table->text('default_value')->nullable()->comment('기본값');
|
||||
$table->json('options')->nullable()->comment('드롭다운 옵션 [{"label": "옵션1", "value": "val1"}]');
|
||||
$table->json('validation_rules')->nullable()->comment('검증 규칙 {"min": 0, "max": 100, "pattern": "regex"}');
|
||||
$table->json('properties')->nullable()->comment('필드 속성 {"unit": "mm", "precision": 2, "format": "YYYY-MM-DD"}');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index('tenant_id', 'idx_item_master_fields_tenant_id');
|
||||
$table->index('category', 'idx_item_master_fields_category');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_item_master_fields_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('item_master_fields');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('item_pages', function (Blueprint $table) {
|
||||
$table->id()->comment('품목 페이지 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->string('page_name')->comment('페이지명');
|
||||
$table->enum('item_type', ['FG', 'PT', 'SM', 'RM', 'CS'])->comment('품목 유형 (FG: 완제품, PT: 반제품, SM: 부자재, RM: 원자재, CS: 소모품)');
|
||||
$table->string('absolute_path', 500)->nullable()->comment('절대 경로');
|
||||
$table->boolean('is_active')->default(true)->comment('활성 여부');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index('tenant_id', 'idx_item_pages_tenant_id');
|
||||
$table->index('item_type', 'idx_item_pages_item_type');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_item_pages_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('item_pages');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('item_sections', function (Blueprint $table) {
|
||||
$table->id()->comment('섹션 인스턴스 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->unsignedBigInteger('page_id')->comment('페이지 ID');
|
||||
$table->string('title')->comment('섹션 제목');
|
||||
$table->enum('type', ['fields', 'bom'])->default('fields')->comment('섹션 타입 (fields: 필드형, bom: BOM형)');
|
||||
$table->integer('order_no')->default(0)->comment('정렬 순서');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index(['tenant_id', 'page_id'], 'idx_item_sections_tenant_page');
|
||||
$table->index(['page_id', 'order_no'], 'idx_item_sections_order');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_item_sections_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
$table->foreign('page_id', 'fk_item_sections_page')
|
||||
->references('id')->on('item_pages')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('item_sections');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('item_fields', function (Blueprint $table) {
|
||||
$table->id()->comment('필드 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->unsignedBigInteger('section_id')->comment('섹션 ID');
|
||||
$table->string('field_name')->comment('필드명');
|
||||
$table->enum('field_type', ['textbox', 'number', 'dropdown', 'checkbox', 'date', 'textarea'])->comment('필드 타입');
|
||||
$table->integer('order_no')->default(0)->comment('정렬 순서');
|
||||
$table->boolean('is_required')->default(false)->comment('필수 여부');
|
||||
$table->text('default_value')->nullable()->comment('기본값');
|
||||
$table->string('placeholder')->nullable()->comment('플레이스홀더');
|
||||
$table->json('display_condition')->nullable()->comment('표시 조건 {"field_id": "1", "operator": "equals", "value": "true"}');
|
||||
$table->json('validation_rules')->nullable()->comment('검증 규칙 {"min": 0, "max": 100, "pattern": "regex"}');
|
||||
$table->json('options')->nullable()->comment('드롭다운 옵션 [{"label": "옵션1", "value": "val1"}]');
|
||||
$table->json('properties')->nullable()->comment('필드 속성 {"unit": "mm", "precision": 2, "format": "YYYY-MM-DD"}');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index(['tenant_id', 'section_id'], 'idx_item_fields_tenant_section');
|
||||
$table->index(['section_id', 'order_no'], 'idx_item_fields_order');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_item_fields_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
$table->foreign('section_id', 'fk_item_fields_section')
|
||||
->references('id')->on('item_sections')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('item_fields');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('item_bom_items', function (Blueprint $table) {
|
||||
$table->id()->comment('BOM 항목 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->unsignedBigInteger('section_id')->comment('섹션 ID');
|
||||
$table->string('item_code', 100)->nullable()->comment('품목 코드');
|
||||
$table->string('item_name')->comment('품목명');
|
||||
$table->decimal('quantity', 15, 4)->default(0)->comment('수량');
|
||||
$table->string('unit', 50)->nullable()->comment('단위');
|
||||
$table->decimal('unit_price', 15, 2)->nullable()->comment('단가');
|
||||
$table->decimal('total_price', 15, 2)->nullable()->comment('총액');
|
||||
$table->text('spec')->nullable()->comment('사양');
|
||||
$table->text('note')->nullable()->comment('비고');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index(['tenant_id', 'section_id'], 'idx_item_bom_items_tenant_section');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_item_bom_items_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
$table->foreign('section_id', 'fk_item_bom_items_section')
|
||||
->references('id')->on('item_sections')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('item_bom_items');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('custom_tabs', function (Blueprint $table) {
|
||||
$table->id()->comment('커스텀 탭 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->string('label')->comment('탭 라벨');
|
||||
$table->string('icon', 100)->nullable()->comment('아이콘');
|
||||
$table->boolean('is_default')->default(false)->comment('기본 탭 여부');
|
||||
$table->integer('order_no')->default(0)->comment('정렬 순서');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자 ID');
|
||||
$table->timestamps();
|
||||
$table->softDeletes()->comment('소프트 삭제');
|
||||
|
||||
// 인덱스
|
||||
$table->index('tenant_id', 'idx_custom_tabs_tenant_id');
|
||||
$table->index(['tenant_id', 'order_no'], 'idx_custom_tabs_order');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_custom_tabs_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('custom_tabs');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tab_columns', function (Blueprint $table) {
|
||||
$table->id()->comment('탭 컬럼 설정 ID');
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->unsignedBigInteger('tab_id')->comment('탭 ID');
|
||||
$table->json('columns')->comment('컬럼 설정 [{"key": "name", "label": "품목명", "visible": true, "order": 0}]');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('생성자 ID');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자 ID');
|
||||
$table->timestamps();
|
||||
|
||||
// 인덱스
|
||||
$table->unique(['tenant_id', 'tab_id'], 'uk_tab_columns_tenant_tab');
|
||||
|
||||
// 외래키
|
||||
$table->foreign('tenant_id', 'fk_tab_columns_tenant')
|
||||
->references('id')->on('tenants')
|
||||
->onDelete('cascade');
|
||||
$table->foreign('tab_id', 'fk_tab_columns_tab')
|
||||
->references('id')->on('custom_tabs')
|
||||
->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tab_columns');
|
||||
}
|
||||
};
|
||||
221
database/seeders/ItemMasterSeeder.php
Normal file
221
database/seeders/ItemMasterSeeder.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\ItemMaster\UnitOption;
|
||||
use App\Models\ItemMaster\SectionTemplate;
|
||||
use App\Models\ItemMaster\ItemMasterField;
|
||||
use App\Models\ItemMaster\ItemPage;
|
||||
use App\Models\ItemMaster\ItemSection;
|
||||
use App\Models\ItemMaster\ItemField;
|
||||
use App\Models\ItemMaster\ItemBomItem;
|
||||
use App\Models\ItemMaster\CustomTab;
|
||||
use App\Models\ItemMaster\TabColumn;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class ItemMasterSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$tenantId = 1; // 기본 테넌트 ID (실제 환경에 맞게 조정)
|
||||
$userId = 1; // 기본 사용자 ID (실제 환경에 맞게 조정)
|
||||
|
||||
// 1. 단위 옵션
|
||||
$units = [
|
||||
['label' => '킬로그램', 'value' => 'kg'],
|
||||
['label' => '개', 'value' => 'EA'],
|
||||
['label' => '미터', 'value' => 'm'],
|
||||
['label' => '밀리미터', 'value' => 'mm'],
|
||||
['label' => '리터', 'value' => 'L'],
|
||||
['label' => '박스', 'value' => 'BOX'],
|
||||
];
|
||||
|
||||
foreach ($units as $unit) {
|
||||
UnitOption::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'label' => $unit['label'],
|
||||
'value' => $unit['value'],
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
// 2. 섹션 템플릿
|
||||
$templates = [
|
||||
['title' => '기본 정보', 'type' => 'fields', 'description' => '제품 기본 정보 입력용 템플릿', 'is_default' => true],
|
||||
['title' => '치수 정보', 'type' => 'fields', 'description' => '제품 치수 정보 입력용 템플릿', 'is_default' => false],
|
||||
['title' => 'BOM 구성', 'type' => 'bom', 'description' => 'BOM 항목 관리용 템플릿', 'is_default' => true],
|
||||
];
|
||||
|
||||
foreach ($templates as $template) {
|
||||
SectionTemplate::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'title' => $template['title'],
|
||||
'type' => $template['type'],
|
||||
'description' => $template['description'],
|
||||
'is_default' => $template['is_default'],
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
// 3. 마스터 필드
|
||||
$masterFields = [
|
||||
['field_name' => '제품명', 'field_type' => 'textbox', 'category' => '기본정보', 'is_common' => true],
|
||||
['field_name' => '제품코드', 'field_type' => 'textbox', 'category' => '기본정보', 'is_common' => true],
|
||||
['field_name' => '규격', 'field_type' => 'textbox', 'category' => '기본정보', 'is_common' => true],
|
||||
['field_name' => '수량', 'field_type' => 'number', 'category' => '재고정보', 'is_common' => true],
|
||||
['field_name' => '단위', 'field_type' => 'dropdown', 'category' => '재고정보', 'is_common' => true, 'options' => [
|
||||
['label' => 'kg', 'value' => 'kg'],
|
||||
['label' => 'EA', 'value' => 'EA'],
|
||||
['label' => 'm', 'value' => 'm'],
|
||||
]],
|
||||
['field_name' => '길이', 'field_type' => 'number', 'category' => '치수정보', 'is_common' => false, 'properties' => ['unit' => 'mm', 'precision' => 2]],
|
||||
['field_name' => '폭', 'field_type' => 'number', 'category' => '치수정보', 'is_common' => false, 'properties' => ['unit' => 'mm', 'precision' => 2]],
|
||||
['field_name' => '높이', 'field_type' => 'number', 'category' => '치수정보', 'is_common' => false, 'properties' => ['unit' => 'mm', 'precision' => 2]],
|
||||
];
|
||||
|
||||
foreach ($masterFields as $field) {
|
||||
ItemMasterField::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'field_name' => $field['field_name'],
|
||||
'field_type' => $field['field_type'],
|
||||
'category' => $field['category'],
|
||||
'is_common' => $field['is_common'],
|
||||
'options' => $field['options'] ?? null,
|
||||
'properties' => $field['properties'] ?? null,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
// 4. 품목 페이지 (5개 유형)
|
||||
$pages = [
|
||||
['page_name' => '완제품 관리', 'item_type' => 'FG', 'absolute_path' => '/FG/완제품 관리'],
|
||||
['page_name' => '반제품 관리', 'item_type' => 'PT', 'absolute_path' => '/PT/반제품 관리'],
|
||||
['page_name' => '부자재 관리', 'item_type' => 'SM', 'absolute_path' => '/SM/부자재 관리'],
|
||||
['page_name' => '원자재 관리', 'item_type' => 'RM', 'absolute_path' => '/RM/원자재 관리'],
|
||||
['page_name' => '소모품 관리', 'item_type' => 'CS', 'absolute_path' => '/CS/소모품 관리'],
|
||||
];
|
||||
|
||||
foreach ($pages as $index => $page) {
|
||||
$itemPage = ItemPage::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'page_name' => $page['page_name'],
|
||||
'item_type' => $page['item_type'],
|
||||
'absolute_path' => $page['absolute_path'],
|
||||
'is_active' => true,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 각 페이지에 기본 섹션 추가
|
||||
$section1 = ItemSection::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'page_id' => $itemPage->id,
|
||||
'title' => '기본 정보',
|
||||
'type' => 'fields',
|
||||
'order_no' => 0,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 섹션에 필드 추가
|
||||
ItemField::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'section_id' => $section1->id,
|
||||
'field_name' => '제품명',
|
||||
'field_type' => 'textbox',
|
||||
'order_no' => 0,
|
||||
'is_required' => true,
|
||||
'placeholder' => '제품명을 입력하세요',
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
ItemField::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'section_id' => $section1->id,
|
||||
'field_name' => '제품코드',
|
||||
'field_type' => 'textbox',
|
||||
'order_no' => 1,
|
||||
'is_required' => true,
|
||||
'placeholder' => '제품코드를 입력하세요',
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
ItemField::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'section_id' => $section1->id,
|
||||
'field_name' => '규격',
|
||||
'field_type' => 'textbox',
|
||||
'order_no' => 2,
|
||||
'is_required' => false,
|
||||
'placeholder' => '규격을 입력하세요',
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// BOM 섹션 (완제품, 반제품만)
|
||||
if (in_array($page['item_type'], ['FG', 'PT'])) {
|
||||
$section2 = ItemSection::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'page_id' => $itemPage->id,
|
||||
'title' => 'BOM 구성',
|
||||
'type' => 'bom',
|
||||
'order_no' => 1,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// BOM 항목 샘플
|
||||
ItemBomItem::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'section_id' => $section2->id,
|
||||
'item_code' => 'MAT-001',
|
||||
'item_name' => '철판',
|
||||
'quantity' => 10.5,
|
||||
'unit' => 'kg',
|
||||
'unit_price' => 5000.00,
|
||||
'total_price' => 52500.00,
|
||||
'spec' => '두께 2mm, 스테인리스',
|
||||
'note' => '샘플 BOM 항목',
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 커스텀 탭
|
||||
$tabs = [
|
||||
['label' => '전체', 'icon' => 'all', 'is_default' => true, 'order_no' => 0],
|
||||
['label' => '완제품', 'icon' => 'product', 'is_default' => false, 'order_no' => 1],
|
||||
['label' => '원자재', 'icon' => 'material', 'is_default' => false, 'order_no' => 2],
|
||||
];
|
||||
|
||||
foreach ($tabs as $tab) {
|
||||
$customTab = CustomTab::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'label' => $tab['label'],
|
||||
'icon' => $tab['icon'],
|
||||
'is_default' => $tab['is_default'],
|
||||
'order_no' => $tab['order_no'],
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 탭별 컬럼 설정
|
||||
TabColumn::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'tab_id' => $customTab->id,
|
||||
'columns' => [
|
||||
['key' => 'name', 'label' => '품목명', 'visible' => true, 'order' => 0],
|
||||
['key' => 'code', 'label' => '품목코드', 'visible' => true, 'order' => 1],
|
||||
['key' => 'type', 'label' => '유형', 'visible' => true, 'order' => 2],
|
||||
['key' => 'price', 'label' => '가격', 'visible' => false, 'order' => 3],
|
||||
],
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
echo "✅ ItemMaster 시드 데이터 생성 완료!\n";
|
||||
echo " - 단위 옵션: ".count($units)."개\n";
|
||||
echo " - 섹션 템플릿: ".count($templates)."개\n";
|
||||
echo " - 마스터 필드: ".count($masterFields)."개\n";
|
||||
echo " - 품목 페이지: ".count($pages)."개\n";
|
||||
echo " - 커스텀 탭: ".count($tabs)."개\n";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user