feat: [interview] 인터뷰 시나리오 고도화 마이그레이션
- interview_projects 테이블 신규 (회사별 프로젝트) - interview_attachments 테이블 신규 (첨부파일 + AI 분석) - interview_knowledge 테이블 신규 (AI 추출 지식) - interview_categories에 project_id, domain 컬럼 추가 - interview_questions에 ai_hint, expected_format, depends_on, domain 추가 - interview_answers에 answer_data, attachments JSON 추가 - interview_sessions에 project_id, session_type, voice_recording_id 추가
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('interview_projects', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->string('company_name', 200)->comment('대상 회사명');
|
||||
$table->string('company_type', 100)->nullable()->comment('업종 (방화셔터, 블라인드 등)');
|
||||
$table->string('contact_person', 100)->nullable()->comment('담당자');
|
||||
$table->string('contact_info', 200)->nullable()->comment('연락처');
|
||||
$table->enum('status', ['draft', 'interviewing', 'analyzing', 'code_generated', 'deployed'])
|
||||
->default('draft')->comment('상태');
|
||||
$table->unsignedBigInteger('target_tenant_id')->nullable()->comment('생성될 테넌트 ID');
|
||||
$table->json('product_categories')->nullable()->comment('제품 카테고리 목록');
|
||||
$table->text('summary')->nullable()->comment('AI 생성 요약');
|
||||
$table->unsignedTinyInteger('progress_percent')->default(0)->comment('전체 진행률');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('등록자');
|
||||
$table->unsignedBigInteger('updated_by')->nullable()->comment('수정자');
|
||||
$table->unsignedBigInteger('deleted_by')->nullable()->comment('삭제자');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->index('tenant_id', 'idx_interview_projects_tenant');
|
||||
$table->index('status', 'idx_interview_projects_status');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('interview_projects');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('interview_attachments', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->unsignedBigInteger('interview_project_id')->comment('인터뷰 프로젝트 ID');
|
||||
$table->enum('file_type', ['excel_template', 'pdf_quote', 'sample_bom', 'price_list', 'photo', 'voice', 'other'])
|
||||
->default('other')->comment('파일 유형');
|
||||
$table->string('file_name', 255)->comment('파일명');
|
||||
$table->string('file_path', 500)->comment('저장 경로');
|
||||
$table->unsignedInteger('file_size')->default(0)->comment('파일 크기 (bytes)');
|
||||
$table->string('mime_type', 100)->nullable()->comment('MIME 타입');
|
||||
$table->json('ai_analysis')->nullable()->comment('AI 분석 결과');
|
||||
$table->enum('ai_analysis_status', ['pending', 'processing', 'completed', 'failed'])
|
||||
->default('pending')->comment('AI 분석 상태');
|
||||
$table->text('description')->nullable()->comment('설명');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('등록자');
|
||||
$table->timestamps();
|
||||
|
||||
$table->index('tenant_id', 'idx_interview_attachments_tenant');
|
||||
$table->index('interview_project_id', 'idx_interview_attachments_project');
|
||||
$table->index('file_type', 'idx_interview_attachments_type');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('interview_attachments');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('interview_knowledge', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('tenant_id')->comment('테넌트 ID');
|
||||
$table->unsignedBigInteger('interview_project_id')->comment('인터뷰 프로젝트 ID');
|
||||
$table->enum('domain', [
|
||||
'product_classification', 'bom_structure', 'dimension_formula',
|
||||
'component_config', 'pricing_structure', 'quantity_formula',
|
||||
'conditional_logic', 'quote_format',
|
||||
])->comment('도메인 영역');
|
||||
$table->enum('knowledge_type', ['fact', 'rule', 'formula', 'mapping', 'range', 'table'])
|
||||
->comment('지식 유형');
|
||||
$table->string('title', 300)->comment('제목');
|
||||
$table->json('content')->comment('구조화된 지식 데이터');
|
||||
$table->enum('source_type', ['interview_answer', 'voice_recording', 'document', 'manual'])
|
||||
->comment('출처 유형');
|
||||
$table->unsignedBigInteger('source_id')->nullable()->comment('출처 레코드 ID');
|
||||
$table->decimal('confidence', 3, 2)->default(0.00)->comment('AI 신뢰도 (0.00~1.00)');
|
||||
$table->boolean('is_verified')->default(false)->comment('사용자 검증 여부');
|
||||
$table->unsignedBigInteger('verified_by')->nullable()->comment('검증자');
|
||||
$table->timestamp('verified_at')->nullable()->comment('검증 일시');
|
||||
$table->unsignedBigInteger('created_by')->nullable()->comment('등록자');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->index('tenant_id', 'idx_interview_knowledge_tenant');
|
||||
$table->index('interview_project_id', 'idx_interview_knowledge_project');
|
||||
$table->index('domain', 'idx_interview_knowledge_domain');
|
||||
$table->index('is_verified', 'idx_interview_knowledge_verified');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('interview_knowledge');
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('interview_categories', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('interview_project_id')->nullable()
|
||||
->after('tenant_id')->comment('프로젝트 연결');
|
||||
$table->string('domain', 50)->nullable()
|
||||
->after('description')->comment('도메인 영역 태그');
|
||||
|
||||
$table->index('interview_project_id', 'idx_interview_categories_project');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('interview_categories', function (Blueprint $table) {
|
||||
$table->dropIndex('idx_interview_categories_project');
|
||||
$table->dropColumn(['interview_project_id', 'domain']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// interview_questions 확장
|
||||
Schema::table('interview_questions', function (Blueprint $table) {
|
||||
$table->text('ai_hint')->nullable()->after('options')->comment('AI 분석 힌트/가이드');
|
||||
$table->string('expected_format', 100)->nullable()->after('ai_hint')->comment('예상 답변 형식 (mm, 원/kg 등)');
|
||||
$table->json('depends_on')->nullable()->after('expected_format')->comment('조건부 표시 조건');
|
||||
$table->string('domain', 50)->nullable()->after('depends_on')->comment('도메인 영역');
|
||||
});
|
||||
|
||||
// question_type 컬럼 확장 (varchar(20) → varchar(50))
|
||||
Schema::table('interview_questions', function (Blueprint $table) {
|
||||
$table->string('question_type', 50)->default('checkbox')
|
||||
->comment('질문유형: checkbox|text|number|select|multi_select|file_upload|formula_input|table_input|bom_tree|price_table|dimension_diagram')
|
||||
->change();
|
||||
});
|
||||
|
||||
// interview_answers 확장
|
||||
Schema::table('interview_answers', function (Blueprint $table) {
|
||||
$table->json('answer_data')->nullable()->after('answer_text')->comment('구조화 답변 (테이블, 수식, BOM 등)');
|
||||
$table->json('attachments')->nullable()->after('answer_data')->comment('첨부 파일 경로 목록');
|
||||
});
|
||||
|
||||
// interview_sessions 확장
|
||||
Schema::table('interview_sessions', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('interview_project_id')->nullable()
|
||||
->after('tenant_id')->comment('프로젝트 ID');
|
||||
$table->string('session_type', 20)->default('checklist')
|
||||
->after('status')->comment('세션 유형: checklist|structured|voice|review');
|
||||
$table->unsignedBigInteger('voice_recording_id')->nullable()
|
||||
->after('session_type')->comment('음성 녹음 ID');
|
||||
|
||||
$table->index('interview_project_id', 'idx_interview_sessions_project');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('interview_sessions', function (Blueprint $table) {
|
||||
$table->dropIndex('idx_interview_sessions_project');
|
||||
$table->dropColumn(['interview_project_id', 'session_type', 'voice_recording_id']);
|
||||
});
|
||||
|
||||
Schema::table('interview_answers', function (Blueprint $table) {
|
||||
$table->dropColumn(['answer_data', 'attachments']);
|
||||
});
|
||||
|
||||
Schema::table('interview_questions', function (Blueprint $table) {
|
||||
$table->string('question_type', 20)->default('checkbox')
|
||||
->comment('질문유형: checkbox/text')->change();
|
||||
$table->dropColumn(['ai_hint', 'expected_format', 'depends_on', 'domain']);
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user