diff --git a/database/migrations/2026_02_10_100000_create_meeting_minutes_table.php b/database/migrations/2026_02_10_100000_create_meeting_minutes_table.php new file mode 100644 index 0000000..91c74aa --- /dev/null +++ b/database/migrations/2026_02_10_100000_create_meeting_minutes_table.php @@ -0,0 +1,51 @@ +id()->comment('ID'); + $table->unsignedBigInteger('tenant_id')->comment('테넌트 ID'); + $table->unsignedBigInteger('user_id')->comment('작성자 ID'); + + $table->string('title', 300)->default('무제 회의록')->comment('회의 제목'); + $table->string('folder', 100)->nullable()->comment('폴더 분류'); + $table->json('participants')->nullable()->comment('참여자 목록'); + + $table->date('meeting_date')->comment('회의 날짜'); + $table->time('meeting_time')->nullable()->comment('회의 시작 시간'); + $table->unsignedInteger('duration_seconds')->default(0)->comment('녹음 총 시간(초)'); + + $table->string('audio_file_path', 500)->nullable()->comment('오디오 GCS 경로'); + $table->string('audio_gcs_uri', 500)->nullable()->comment('오디오 GCS URI'); + $table->unsignedBigInteger('audio_file_size')->nullable()->comment('오디오 파일 크기(bytes)'); + + $table->longText('full_transcript')->nullable()->comment('전체 트랜스크립트'); + + $table->longText('summary')->nullable()->comment('AI 요약'); + $table->json('decisions')->nullable()->comment('결정사항 목록'); + $table->json('action_items')->nullable()->comment('액션아이템 목록'); + + $table->string('status', 20)->default('DRAFT')->comment('상태 (DRAFT/RECORDING/PROCESSING/COMPLETED/FAILED)'); + $table->string('stt_language', 10)->default('ko-KR')->comment('STT 언어'); + + $table->timestamps(); + $table->softDeletes(); + + $table->index('tenant_id', 'idx_mm_tenant'); + $table->index('user_id', 'idx_mm_user'); + $table->index(['tenant_id', 'meeting_date'], 'idx_mm_tenant_date'); + $table->index('status', 'idx_mm_status'); + }); + } + + public function down(): void + { + Schema::dropIfExists('meeting_minutes'); + } +}; diff --git a/database/migrations/2026_02_10_100001_create_meeting_minute_segments_table.php b/database/migrations/2026_02_10_100001_create_meeting_minute_segments_table.php new file mode 100644 index 0000000..328f6e3 --- /dev/null +++ b/database/migrations/2026_02_10_100001_create_meeting_minute_segments_table.php @@ -0,0 +1,39 @@ +id()->comment('ID'); + $table->unsignedBigInteger('meeting_minute_id')->comment('회의록 ID'); + $table->unsignedInteger('segment_order')->comment('세그먼트 순서'); + + $table->string('speaker_name', 100)->default('화자 1')->comment('화자 이름'); + $table->string('speaker_label', 20)->nullable()->comment('화자 라벨'); + $table->text('text')->comment('발화 텍스트'); + + $table->unsignedInteger('start_time_ms')->default(0)->comment('시작 시간(ms)'); + $table->unsignedInteger('end_time_ms')->nullable()->comment('종료 시간(ms)'); + $table->boolean('is_manual_speaker')->default(true)->comment('수동 화자 전환 여부'); + + $table->timestamps(); + + $table->index('meeting_minute_id', 'idx_mms_meeting'); + $table->index(['meeting_minute_id', 'segment_order'], 'idx_mms_meeting_order'); + + $table->foreign('meeting_minute_id', 'fk_mms_meeting') + ->references('id')->on('meeting_minutes') + ->onDelete('cascade'); + }); + } + + public function down(): void + { + Schema::dropIfExists('meeting_minute_segments'); + } +};