'integer', 'options' => 'array', 'started_at' => 'datetime', 'ended_at' => 'datetime', ]; /** * 대상 유형 상수 */ public const TARGET_ALL = 'all'; public const TARGET_DEPARTMENT = 'department'; /** * 대상 유형 목록 */ public const TARGET_TYPES = [ self::TARGET_ALL => '전사', self::TARGET_DEPARTMENT => '부서', ]; /** * 상태 상수 */ public const STATUS_ACTIVE = 'active'; public const STATUS_INACTIVE = 'inactive'; /** * 상태 목록 */ public const STATUSES = [ self::STATUS_ACTIVE => '사용', self::STATUS_INACTIVE => '사용안함', ]; /** * 부서 관계 (target_type='department' 일 때) */ public function department(): BelongsTo { return $this->belongsTo(Department::class, 'target_id'); } /** * 작성자 관계 */ public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } /** * 수정자 관계 */ public function updater(): BelongsTo { return $this->belongsTo(User::class, 'updated_by'); } /** * 대상 유형 라벨 속성 */ public function getTargetTypeLabelAttribute(): string { return self::TARGET_TYPES[$this->target_type] ?? $this->target_type; } /** * 상태 라벨 속성 */ public function getStatusLabelAttribute(): string { return self::STATUSES[$this->status] ?? $this->status; } /** * 대상명 속성 (전사 또는 부서명) */ public function getTargetNameAttribute(): string { if ($this->target_type === self::TARGET_ALL) { return '전사'; } return $this->department?->name ?? '-'; } /** * 활성 스코프 (상태=active AND 기간 내) */ public function scopeActive(Builder $query): Builder { $now = now(); return $query->where('status', self::STATUS_ACTIVE) ->where(function ($q) use ($now) { $q->whereNull('started_at') ->orWhere('started_at', '<=', $now); }) ->where(function ($q) use ($now) { $q->whereNull('ended_at') ->orWhere('ended_at', '>=', $now); }); } /** * 상태별 스코프 */ public function scopeStatus(Builder $query, string $status): Builder { return $query->where('status', $status); } /** * 대상 유형별 스코프 */ public function scopeTargetType(Builder $query, string $targetType): Builder { return $query->where('target_type', $targetType); } /** * 사용자 대상 팝업 스코프 (전사 또는 사용자 부서) */ public function scopeForUser(Builder $query, ?int $departmentId = null): Builder { return $query->where(function ($q) use ($departmentId) { $q->where('target_type', self::TARGET_ALL); if ($departmentId) { $q->orWhere(function ($q) use ($departmentId) { $q->where('target_type', self::TARGET_DEPARTMENT) ->where('target_id', $departmentId); }); } }); } /** * options 헬퍼 메서드 */ public function getOption(string $key, mixed $default = null): mixed { return data_get($this->options, $key, $default); } /** * options 설정 헬퍼 메서드 */ public function setOption(string $key, mixed $value): void { $options = $this->options ?? []; data_set($options, $key, $value); $this->options = $options; } }