'integer', 'overtime_hours' => 'integer', 'overtime_limit' => 'integer', 'break_minutes' => 'integer', ]; protected $attributes = [ 'work_type' => 'fixed', 'standard_hours' => 40, 'overtime_hours' => 12, 'overtime_limit' => 52, 'start_time' => '09:00:00', 'end_time' => '18:00:00', 'break_minutes' => 60, 'break_start' => '12:00:00', 'break_end' => '13:00:00', ]; // ========================================================================= // 상수 정의 // ========================================================================= public const TYPE_FIXED = 'fixed'; // 고정 근무 public const TYPE_FLEXIBLE = 'flexible'; // 유연 근무 public const TYPE_CUSTOM = 'custom'; // 커스텀 근무 public const WORK_TYPES = [ self::TYPE_FIXED, self::TYPE_FLEXIBLE, self::TYPE_CUSTOM, ]; public const DEFAULT_WORK_DAYS = ['mon', 'tue', 'wed', 'thu', 'fri']; /** * 숫자 → 요일 문자열 매핑 */ public const DAY_INDEX_MAP = [ 1 => 'mon', 2 => 'tue', 3 => 'wed', 4 => 'thu', 5 => 'fri', 6 => 'sat', 7 => 'sun', 0 => 'sun', // 일요일이 0인 경우도 처리 ]; // ========================================================================= // Accessors & Mutators // ========================================================================= /** * work_days 조회 시 숫자를 문자열로 변환 */ protected function workDays(): \Illuminate\Database\Eloquent\Casts\Attribute { return \Illuminate\Database\Eloquent\Casts\Attribute::make( get: function ($value) { $days = is_string($value) ? json_decode($value, true) : $value; if (! is_array($days)) { return self::DEFAULT_WORK_DAYS; } // 숫자가 포함된 경우 문자열로 변환 return array_values(array_unique(array_map(function ($day) { if (is_int($day) || is_numeric($day)) { return self::DAY_INDEX_MAP[(int) $day] ?? 'mon'; } return $day; }, $days))); }, set: function ($value) { if (! is_array($value)) { return json_encode(self::DEFAULT_WORK_DAYS); } // 항상 문자열 배열로 저장 $days = array_values(array_unique(array_map(function ($day) { if (is_int($day) || is_numeric($day)) { return self::DAY_INDEX_MAP[(int) $day] ?? 'mon'; } return $day; }, $value))); return json_encode($days); } ); } // ========================================================================= // 헬퍼 메서드 // ========================================================================= /** * 근무 유형 라벨 */ public function getWorkTypeLabelAttribute(): string { return match ($this->work_type) { self::TYPE_FIXED => '고정근무', self::TYPE_FLEXIBLE => '유연근무', self::TYPE_CUSTOM => '커스텀', default => $this->work_type, }; } /** * 일일 근무시간 계산 (분) */ public function getDailyWorkMinutesAttribute(): int { $start = strtotime($this->start_time); $end = strtotime($this->end_time); $totalMinutes = ($end - $start) / 60; return (int) ($totalMinutes - $this->break_minutes); } }