- MeetingLog 모델 (BelongsToTenant, SoftDeletes) - GoogleCloudService (GCS 업로드, STT API) - MeetingLogService (Claude API 요약) - MeetingLogController (HTMX/JSON 듀얼 응답) - 순수 Tailwind CSS UI 구현 - API 라우트 8개 엔드포인트 등록
120 lines
2.7 KiB
PHP
120 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Traits\BelongsToTenant;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
/**
|
|
* 회의록 모델 (웹 녹음 AI 요약)
|
|
*
|
|
* admin_meeting_logs 테이블을 사용합니다.
|
|
*/
|
|
class MeetingLog extends Model
|
|
{
|
|
use BelongsToTenant, SoftDeletes;
|
|
|
|
protected $table = 'admin_meeting_logs';
|
|
|
|
protected $fillable = [
|
|
'tenant_id',
|
|
'user_id',
|
|
'title',
|
|
'audio_file_path',
|
|
'audio_gcs_uri',
|
|
'transcript_text',
|
|
'summary_text',
|
|
'status',
|
|
'duration_seconds',
|
|
'file_expiry_date',
|
|
];
|
|
|
|
protected $casts = [
|
|
'duration_seconds' => 'integer',
|
|
'file_expiry_date' => 'datetime',
|
|
'created_at' => 'datetime',
|
|
'updated_at' => 'datetime',
|
|
'deleted_at' => 'datetime',
|
|
];
|
|
|
|
/**
|
|
* 상태 상수
|
|
*/
|
|
public const STATUS_PENDING = 'PENDING';
|
|
|
|
public const STATUS_PROCESSING = 'PROCESSING';
|
|
|
|
public const STATUS_COMPLETED = 'COMPLETED';
|
|
|
|
public const STATUS_FAILED = 'FAILED';
|
|
|
|
/**
|
|
* 작성자 관계
|
|
*/
|
|
public function user(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class);
|
|
}
|
|
|
|
/**
|
|
* 녹음 시간 포맷 (MM:SS)
|
|
*/
|
|
public function getFormattedDurationAttribute(): string
|
|
{
|
|
if (! $this->duration_seconds) {
|
|
return '00:00';
|
|
}
|
|
|
|
$minutes = floor($this->duration_seconds / 60);
|
|
$seconds = $this->duration_seconds % 60;
|
|
|
|
return sprintf('%02d:%02d', $minutes, $seconds);
|
|
}
|
|
|
|
/**
|
|
* 상태 레이블
|
|
*/
|
|
public function getStatusLabelAttribute(): string
|
|
{
|
|
return match ($this->status) {
|
|
self::STATUS_PENDING => '대기중',
|
|
self::STATUS_PROCESSING => '처리중',
|
|
self::STATUS_COMPLETED => '완료',
|
|
self::STATUS_FAILED => '실패',
|
|
default => $this->status,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 상태 색상 (Tailwind CSS)
|
|
*/
|
|
public function getStatusColorAttribute(): string
|
|
{
|
|
return match ($this->status) {
|
|
self::STATUS_PENDING => 'badge-warning',
|
|
self::STATUS_PROCESSING => 'badge-info',
|
|
self::STATUS_COMPLETED => 'badge-success',
|
|
self::STATUS_FAILED => 'badge-error',
|
|
default => 'badge-ghost',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 처리 완료 여부
|
|
*/
|
|
public function isCompleted(): bool
|
|
{
|
|
return $this->status === self::STATUS_COMPLETED;
|
|
}
|
|
|
|
/**
|
|
* 처리 중 여부
|
|
*/
|
|
public function isProcessing(): bool
|
|
{
|
|
return $this->status === self::STATUS_PROCESSING;
|
|
}
|
|
}
|