- 78개 MNG 전용 모델에 $connection = 'codebridge' 재적용 - config/database.php codebridge connection 포함
206 lines
5.0 KiB
PHP
206 lines
5.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Admin;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
/**
|
|
* API Flow Tester - 실행 이력 모델
|
|
*
|
|
* @property int $id
|
|
* @property int $flow_id
|
|
* @property string $status
|
|
* @property \Carbon\Carbon|null $started_at
|
|
* @property \Carbon\Carbon|null $completed_at
|
|
* @property int|null $duration_ms
|
|
* @property int|null $total_steps
|
|
* @property int $completed_steps
|
|
* @property int|null $failed_step
|
|
* @property array|null $execution_log
|
|
* @property array|null $input_variables
|
|
* @property string|null $error_message
|
|
* @property int|null $executed_by
|
|
* @property \Carbon\Carbon $created_at
|
|
*/
|
|
class AdminApiFlowRun extends Model
|
|
{
|
|
// 상태 상수
|
|
public const STATUS_PENDING = 'PENDING';
|
|
|
|
public const STATUS_RUNNING = 'RUNNING';
|
|
|
|
public const STATUS_SUCCESS = 'SUCCESS';
|
|
|
|
public const STATUS_FAILED = 'FAILED';
|
|
|
|
public const STATUS_PARTIAL = 'PARTIAL';
|
|
|
|
protected $table = 'admin_api_flow_runs';
|
|
|
|
public $timestamps = false; // created_at만 사용
|
|
|
|
protected $fillable = [
|
|
'flow_id',
|
|
'status',
|
|
'started_at',
|
|
'completed_at',
|
|
'duration_ms',
|
|
'total_steps',
|
|
'completed_steps',
|
|
'failed_step',
|
|
'execution_log',
|
|
'input_variables',
|
|
'error_message',
|
|
'api_logs',
|
|
'executed_by',
|
|
];
|
|
|
|
protected $casts = [
|
|
'flow_id' => 'integer',
|
|
'created_at' => 'datetime',
|
|
'started_at' => 'datetime',
|
|
'completed_at' => 'datetime',
|
|
'duration_ms' => 'integer',
|
|
'total_steps' => 'integer',
|
|
'completed_steps' => 'integer',
|
|
'failed_step' => 'integer',
|
|
'execution_log' => 'array',
|
|
'input_variables' => 'array',
|
|
'api_logs' => 'array',
|
|
'executed_by' => 'integer',
|
|
];
|
|
|
|
/**
|
|
* 상태별 필터링
|
|
*/
|
|
public function scopeStatus($query, string $status)
|
|
{
|
|
return $query->where('status', $status);
|
|
}
|
|
|
|
/**
|
|
* 성공한 실행만 조회
|
|
*/
|
|
public function scopeSuccessful($query)
|
|
{
|
|
return $query->where('status', self::STATUS_SUCCESS);
|
|
}
|
|
|
|
/**
|
|
* 실패한 실행만 조회
|
|
*/
|
|
public function scopeFailed($query)
|
|
{
|
|
return $query->where('status', self::STATUS_FAILED);
|
|
}
|
|
|
|
/**
|
|
* 관계: 플로우
|
|
*/
|
|
public function flow(): BelongsTo
|
|
{
|
|
return $this->belongsTo(AdminApiFlow::class, 'flow_id');
|
|
}
|
|
|
|
/**
|
|
* 관계: 실행자
|
|
*/
|
|
public function executor(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'executed_by');
|
|
}
|
|
|
|
/**
|
|
* 실행 중인지 확인
|
|
*/
|
|
public function isRunning(): bool
|
|
{
|
|
return $this->status === self::STATUS_RUNNING;
|
|
}
|
|
|
|
/**
|
|
* 완료되었는지 확인 (성공/실패/부분 포함)
|
|
*/
|
|
public function isCompleted(): bool
|
|
{
|
|
return in_array($this->status, [
|
|
self::STATUS_SUCCESS,
|
|
self::STATUS_FAILED,
|
|
self::STATUS_PARTIAL,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 진행률 반환 (0-100)
|
|
*/
|
|
public function getProgressAttribute(): int
|
|
{
|
|
if (! $this->total_steps || $this->total_steps === 0) {
|
|
return 0;
|
|
}
|
|
|
|
return (int) round(($this->completed_steps / $this->total_steps) * 100);
|
|
}
|
|
|
|
/**
|
|
* 상태 라벨 반환 (한글)
|
|
*/
|
|
public function getStatusLabelAttribute(): string
|
|
{
|
|
return match ($this->status) {
|
|
self::STATUS_PENDING => '대기 중',
|
|
self::STATUS_RUNNING => '실행 중',
|
|
self::STATUS_SUCCESS => '성공',
|
|
self::STATUS_FAILED => '실패',
|
|
self::STATUS_PARTIAL => '부분 성공',
|
|
default => $this->status,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 상태 색상 반환 (Tailwind CSS class)
|
|
*/
|
|
public function getStatusColorAttribute(): string
|
|
{
|
|
return match ($this->status) {
|
|
self::STATUS_PENDING => 'bg-gray-100 text-gray-600',
|
|
self::STATUS_RUNNING => 'bg-blue-100 text-blue-700',
|
|
self::STATUS_SUCCESS => 'bg-green-100 text-green-700',
|
|
self::STATUS_FAILED => 'bg-red-100 text-red-700',
|
|
self::STATUS_PARTIAL => 'bg-yellow-100 text-yellow-700',
|
|
default => 'bg-gray-100 text-gray-600',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* API 로그 개수 반환
|
|
*/
|
|
public function getApiLogCountAttribute(): int
|
|
{
|
|
return is_array($this->api_logs) ? count($this->api_logs) : 0;
|
|
}
|
|
|
|
/**
|
|
* API 로그에 오류가 있는지 확인
|
|
*/
|
|
public function hasApiErrors(): bool
|
|
{
|
|
if (! is_array($this->api_logs)) {
|
|
return false;
|
|
}
|
|
|
|
foreach ($this->api_logs as $log) {
|
|
if (isset($log['type']) && $log['type'] === 'response') {
|
|
$status = $log['status'] ?? 0;
|
|
if ($status >= 400) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|