chore: 누락된 마이그레이션 추가

- create_quote_formula_tables: 견적 수식 테이블 5개
  - quote_formula_categories (카테고리)
  - quote_formulas (수식)
  - quote_formula_ranges (범위값)
  - quote_formula_mappings (매핑값)
  - quote_formula_items (품목 출력)

- add_api_logs_to_admin_api_flow_runs_table: API Flow 로그 컬럼
This commit is contained in:
2025-12-04 22:20:09 +09:00
parent 40ca8b8697
commit 2b57910ca5
2 changed files with 187 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
<?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
{
// 1. 견적 수식 카테고리
Schema::create('quote_formula_categories', function (Blueprint $table) {
$table->id();
$table->foreignId('tenant_id')->constrained()->comment('테넌트 ID');
// 기본 정보
$table->string('code', 50)->comment('카테고리 코드 (예: BASIC_INFO, PRODUCTION_SIZE)');
$table->string('name', 100)->comment('카테고리 이름 (예: 기본정보, 제작사이즈)');
$table->text('description')->nullable()->comment('카테고리 설명');
// 정렬 및 상태
$table->unsignedInteger('sort_order')->default(0)->comment('실행 순서');
$table->boolean('is_active')->default(true)->comment('활성화 여부');
// 감사
$table->foreignId('created_by')->nullable()->comment('생성자');
$table->foreignId('updated_by')->nullable()->comment('수정자');
$table->timestamps();
$table->softDeletes();
// 인덱스
$table->index(['tenant_id', 'sort_order'], 'idx_tenant_sort');
$table->index('code', 'idx_code');
$table->unique(['tenant_id', 'code', 'deleted_at'], 'uq_tenant_code');
});
// 2. 견적 수식
Schema::create('quote_formulas', function (Blueprint $table) {
$table->id();
$table->foreignId('tenant_id')->constrained()->comment('테넌트 ID');
$table->foreignId('category_id')->constrained('quote_formula_categories')->cascadeOnDelete()->comment('카테고리 ID');
$table->foreignId('product_id')->nullable()->comment('특정 제품용 수식 (NULL = 공통)');
// 수식 정보
$table->string('name', 200)->comment('수식 이름');
$table->string('variable', 50)->comment('변수명 (예: W1, H1, M)');
$table->enum('type', ['input', 'calculation', 'range', 'mapping'])->default('calculation')->comment('수식 유형');
// 수식 내용
$table->text('formula')->nullable()->comment('계산식 (type=calculation일 때)');
$table->enum('output_type', ['variable', 'item'])->default('variable')->comment('결과 타입');
// 메타 데이터
$table->text('description')->nullable()->comment('수식 설명');
$table->unsignedInteger('sort_order')->default(0)->comment('카테고리 내 순서');
$table->boolean('is_active')->default(true)->comment('활성화 여부');
// 감사
$table->foreignId('created_by')->nullable()->comment('생성자');
$table->foreignId('updated_by')->nullable()->comment('수정자');
$table->timestamps();
$table->softDeletes();
// 인덱스
$table->index('tenant_id', 'idx_tenant');
$table->index(['category_id', 'sort_order'], 'idx_category_sort');
$table->index('variable', 'idx_variable');
$table->index('product_id', 'idx_product');
});
// 3. 수식 범위별 값
Schema::create('quote_formula_ranges', function (Blueprint $table) {
$table->id();
$table->foreignId('formula_id')->constrained('quote_formulas')->cascadeOnDelete()->comment('수식 ID');
// 범위 조건
$table->decimal('min_value', 15, 4)->nullable()->comment('최소값 (NULL = 제한없음)');
$table->decimal('max_value', 15, 4)->nullable()->comment('최대값 (NULL = 제한없음)');
$table->string('condition_variable', 50)->comment('조건 변수 (예: M, K)');
// 결과
$table->string('result_value', 500)->comment('결과값 (수식 또는 고정값)');
$table->enum('result_type', ['fixed', 'formula'])->default('fixed')->comment('결과 유형');
// 정렬
$table->unsignedInteger('sort_order')->default(0);
$table->timestamps();
// 인덱스
$table->index('formula_id', 'idx_formula');
});
// 4. 수식 매핑 값
Schema::create('quote_formula_mappings', function (Blueprint $table) {
$table->id();
$table->foreignId('formula_id')->constrained('quote_formulas')->cascadeOnDelete()->comment('수식 ID');
// 매핑 조건
$table->string('source_variable', 50)->comment('소스 변수 (예: GT)');
$table->string('source_value', 200)->comment('소스 값 (예: 벽부, 노출)');
// 결과
$table->string('result_value', 500)->comment('결과값');
$table->enum('result_type', ['fixed', 'formula'])->default('fixed');
// 정렬
$table->unsignedInteger('sort_order')->default(0);
$table->timestamps();
// 인덱스
$table->index('formula_id', 'idx_formula');
$table->index(['source_variable', 'source_value'], 'idx_source');
});
// 5. 수식 품목 출력
Schema::create('quote_formula_items', function (Blueprint $table) {
$table->id();
$table->foreignId('formula_id')->constrained('quote_formulas')->cascadeOnDelete()->comment('수식 ID');
// 품목 정보
$table->string('item_code', 50)->comment('품목 코드');
$table->string('item_name', 200)->comment('품목명');
$table->string('specification', 100)->nullable()->comment('규격');
$table->string('unit', 20)->comment('단위 (M, M2, EA 등)');
// 수량 계산
$table->string('quantity_formula', 500)->comment('수량 계산식');
// 단가 연결
$table->string('unit_price_formula', 500)->nullable()->comment('단가 계산식 (NULL = 품목마스터 참조)');
// 정렬
$table->unsignedInteger('sort_order')->default(0);
$table->timestamps();
// 인덱스
$table->index('formula_id', 'idx_formula');
$table->index('item_code', 'idx_item_code');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('quote_formula_items');
Schema::dropIfExists('quote_formula_mappings');
Schema::dropIfExists('quote_formula_ranges');
Schema::dropIfExists('quote_formulas');
Schema::dropIfExists('quote_formula_categories');
}
};

View File

@@ -0,0 +1,28 @@
<?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::table('admin_api_flow_runs', function (Blueprint $table) {
$table->json('api_logs')->nullable()->after('error_message')->comment('API Request/Response 로그');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('admin_api_flow_runs', function (Blueprint $table) {
$table->dropColumn('api_logs');
});
}
};