- 사용량 조회 API (GET /subscriptions/usage)
- 데이터 내보내기 API (POST/GET /subscriptions/export)
- 결제 명세서 API (GET /payments/{id}/statement)
- DataExport 모델 및 마이그레이션 추가
207 lines
5.2 KiB
PHP
207 lines
5.2 KiB
PHP
<?php
|
|
|
|
namespace App\Models\Tenants;
|
|
|
|
use App\Models\Members\User;
|
|
use App\Traits\BelongsToTenant;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
/**
|
|
* 데이터 내보내기 모델
|
|
*
|
|
* @property int $id
|
|
* @property int $tenant_id 테넌트 ID
|
|
* @property string $export_type 내보내기 유형
|
|
* @property string $status 상태
|
|
* @property string|null $file_path 파일 경로
|
|
* @property string|null $file_name 파일명
|
|
* @property int|null $file_size 파일 크기
|
|
* @property array|null $options 옵션
|
|
* @property \Carbon\Carbon|null $started_at 시작 시간
|
|
* @property \Carbon\Carbon|null $completed_at 완료 시간
|
|
* @property string|null $error_message 에러 메시지
|
|
* @property int|null $created_by 생성자
|
|
*/
|
|
class DataExport extends Model
|
|
{
|
|
use BelongsToTenant;
|
|
|
|
// =========================================================================
|
|
// 상수 정의
|
|
// =========================================================================
|
|
|
|
/** 내보내기 유형 */
|
|
public const TYPE_ALL = 'all';
|
|
|
|
public const TYPE_USERS = 'users';
|
|
|
|
public const TYPE_PRODUCTS = 'products';
|
|
|
|
public const TYPE_ORDERS = 'orders';
|
|
|
|
public const TYPE_CLIENTS = 'clients';
|
|
|
|
public const TYPES = [
|
|
self::TYPE_ALL,
|
|
self::TYPE_USERS,
|
|
self::TYPE_PRODUCTS,
|
|
self::TYPE_ORDERS,
|
|
self::TYPE_CLIENTS,
|
|
];
|
|
|
|
/** 상태 */
|
|
public const STATUS_PENDING = 'pending';
|
|
|
|
public const STATUS_PROCESSING = 'processing';
|
|
|
|
public const STATUS_COMPLETED = 'completed';
|
|
|
|
public const STATUS_FAILED = 'failed';
|
|
|
|
public const STATUSES = [
|
|
self::STATUS_PENDING,
|
|
self::STATUS_PROCESSING,
|
|
self::STATUS_COMPLETED,
|
|
self::STATUS_FAILED,
|
|
];
|
|
|
|
/** 상태 라벨 */
|
|
public const STATUS_LABELS = [
|
|
self::STATUS_PENDING => '대기중',
|
|
self::STATUS_PROCESSING => '처리중',
|
|
self::STATUS_COMPLETED => '완료',
|
|
self::STATUS_FAILED => '실패',
|
|
];
|
|
|
|
// =========================================================================
|
|
// 모델 설정
|
|
// =========================================================================
|
|
|
|
protected $fillable = [
|
|
'tenant_id',
|
|
'export_type',
|
|
'status',
|
|
'file_path',
|
|
'file_name',
|
|
'file_size',
|
|
'options',
|
|
'started_at',
|
|
'completed_at',
|
|
'error_message',
|
|
'created_by',
|
|
];
|
|
|
|
protected $casts = [
|
|
'options' => 'array',
|
|
'file_size' => 'integer',
|
|
'started_at' => 'datetime',
|
|
'completed_at' => 'datetime',
|
|
];
|
|
|
|
protected $attributes = [
|
|
'status' => self::STATUS_PENDING,
|
|
];
|
|
|
|
// =========================================================================
|
|
// 관계
|
|
// =========================================================================
|
|
|
|
public function tenant(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Tenant::class);
|
|
}
|
|
|
|
public function creator(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'created_by');
|
|
}
|
|
|
|
// =========================================================================
|
|
// 접근자
|
|
// =========================================================================
|
|
|
|
/**
|
|
* 상태 라벨
|
|
*/
|
|
public function getStatusLabelAttribute(): string
|
|
{
|
|
return self::STATUS_LABELS[$this->status] ?? $this->status;
|
|
}
|
|
|
|
/**
|
|
* 파일 크기 포맷
|
|
*/
|
|
public function getFileSizeFormattedAttribute(): string
|
|
{
|
|
if (! $this->file_size) {
|
|
return '-';
|
|
}
|
|
|
|
$units = ['B', 'KB', 'MB', 'GB'];
|
|
$bytes = max($this->file_size, 0);
|
|
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
|
$pow = min($pow, count($units) - 1);
|
|
$bytes /= (1 << (10 * $pow));
|
|
|
|
return round($bytes, 2).' '.$units[$pow];
|
|
}
|
|
|
|
/**
|
|
* 완료 여부
|
|
*/
|
|
public function getIsCompletedAttribute(): bool
|
|
{
|
|
return $this->status === self::STATUS_COMPLETED;
|
|
}
|
|
|
|
/**
|
|
* 다운로드 가능 여부
|
|
*/
|
|
public function getIsDownloadableAttribute(): bool
|
|
{
|
|
return $this->status === self::STATUS_COMPLETED && $this->file_path;
|
|
}
|
|
|
|
// =========================================================================
|
|
// 헬퍼 메서드
|
|
// =========================================================================
|
|
|
|
/**
|
|
* 처리 시작
|
|
*/
|
|
public function markAsProcessing(): bool
|
|
{
|
|
$this->status = self::STATUS_PROCESSING;
|
|
$this->started_at = now();
|
|
|
|
return $this->save();
|
|
}
|
|
|
|
/**
|
|
* 처리 완료
|
|
*/
|
|
public function markAsCompleted(string $filePath, string $fileName, int $fileSize): bool
|
|
{
|
|
$this->status = self::STATUS_COMPLETED;
|
|
$this->file_path = $filePath;
|
|
$this->file_name = $fileName;
|
|
$this->file_size = $fileSize;
|
|
$this->completed_at = now();
|
|
|
|
return $this->save();
|
|
}
|
|
|
|
/**
|
|
* 처리 실패
|
|
*/
|
|
public function markAsFailed(string $errorMessage): bool
|
|
{
|
|
$this->status = self::STATUS_FAILED;
|
|
$this->error_message = $errorMessage;
|
|
$this->completed_at = now();
|
|
|
|
return $this->save();
|
|
}
|
|
}
|