'array', 'base_date' => 'date', ]; protected $fillable = [ 'tenant_id', 'user_id', 'base_date', 'status', 'json_details', 'remarks', 'created_by', 'updated_by', 'deleted_by', ]; /** * 기본값 설정 */ protected $attributes = [ 'status' => 'onTime', ]; // ========================================================================= // 관계 정의 // ========================================================================= /** * 사용자 관계 */ public function user(): BelongsTo { return $this->belongsTo(User::class, 'user_id'); } /** * 생성자 관계 */ public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } /** * 수정자 관계 */ public function updater(): BelongsTo { return $this->belongsTo(User::class, 'updated_by'); } // ========================================================================= // json_details 헬퍼 메서드 (Accessor) // ========================================================================= /** * 출근 시간 */ public function getCheckInAttribute(): ?string { return $this->json_details['check_in'] ?? null; } /** * 퇴근 시간 */ public function getCheckOutAttribute(): ?string { return $this->json_details['check_out'] ?? null; } /** * GPS 데이터 */ public function getGpsDataAttribute(): ?array { return $this->json_details['gps_data'] ?? null; } /** * 외근 정보 */ public function getExternalWorkAttribute(): ?array { return $this->json_details['external_work'] ?? null; } /** * 다중 출퇴근 기록 (여러 번 출퇴근) */ public function getMultipleEntriesAttribute(): ?array { return $this->json_details['multiple_entries'] ?? null; } /** * 근무 시간 (분 단위) */ public function getWorkMinutesAttribute(): ?int { return isset($this->json_details['work_minutes']) ? (int) $this->json_details['work_minutes'] : null; } /** * 초과 근무 시간 (분 단위) */ public function getOvertimeMinutesAttribute(): ?int { return isset($this->json_details['overtime_minutes']) ? (int) $this->json_details['overtime_minutes'] : null; } /** * 지각 시간 (분 단위) */ public function getLateMinutesAttribute(): ?int { return isset($this->json_details['late_minutes']) ? (int) $this->json_details['late_minutes'] : null; } /** * 조퇴 시간 (분 단위) */ public function getEarlyLeaveMinutesAttribute(): ?int { return isset($this->json_details['early_leave_minutes']) ? (int) $this->json_details['early_leave_minutes'] : null; } /** * 휴가 유형 (vacation 상태일 때) */ public function getVacationTypeAttribute(): ?string { return $this->json_details['vacation_type'] ?? null; } // ========================================================================= // json_details 업데이트 메서드 // ========================================================================= /** * json_details에서 특정 키 값 설정 */ public function setJsonDetailsValue(string $key, mixed $value): void { $jsonDetails = $this->json_details ?? []; if ($value === null) { unset($jsonDetails[$key]); } else { $jsonDetails[$key] = $value; } $this->json_details = $jsonDetails; } /** * json_details에서 특정 키 값 가져오기 */ public function getJsonDetailsValue(string $key, mixed $default = null): mixed { return $this->json_details[$key] ?? $default; } /** * 출퇴근 정보 일괄 업데이트 */ public function updateAttendanceDetails(array $data): void { $jsonDetails = $this->json_details ?? []; $allowedKeys = [ 'check_in', 'check_out', 'gps_data', 'external_work', 'multiple_entries', 'work_minutes', 'overtime_minutes', 'late_minutes', 'early_leave_minutes', 'vacation_type', ]; foreach ($allowedKeys as $key) { if (array_key_exists($key, $data)) { if ($data[$key] === null) { unset($jsonDetails[$key]); } else { $jsonDetails[$key] = $data[$key]; } } } $this->json_details = $jsonDetails; } // ========================================================================= // 스코프 // ========================================================================= /** * 특정 날짜의 근태 조회 */ public function scopeOnDate($query, string $date) { return $query->whereDate('base_date', $date); } /** * 특정 기간의 근태 조회 */ public function scopeBetweenDates($query, string $startDate, string $endDate) { return $query->whereBetween('base_date', [$startDate, $endDate]); } /** * 특정 사용자의 근태 조회 */ public function scopeForUser($query, int $userId) { return $query->where('user_id', $userId); } /** * 특정 상태의 근태 조회 */ public function scopeWithStatus($query, string $status) { return $query->where('status', $status); } }