'required|integer|exists:users,id', 'base_date' => 'required|date', 'status' => 'nullable|in:onTime,late,absent,vacation,businessTrip,fieldWork,overtime,remote', 'remarks' => 'nullable|string|max:500', // json_details 객체로 전달되는 경우 (프론트엔드 기본 형식) 'json_details' => 'nullable|array', 'json_details.check_in' => 'nullable|date_format:H:i:s', 'json_details.check_out' => 'nullable|date_format:H:i:s', 'json_details.gps_data' => 'nullable|array', 'json_details.work_minutes' => 'nullable|integer|min:0', 'json_details.overtime_minutes' => 'nullable|integer|min:0', 'json_details.late_minutes' => 'nullable|integer|min:0', 'json_details.early_leave_minutes' => 'nullable|integer|min:0', 'json_details.vacation_type' => 'nullable|string|max:50', 'json_details.reason' => 'nullable|string|max:500', 'json_details.break_time' => 'nullable|string|max:50', // 최상위 레벨 필드 (호환성 유지) 'check_in' => 'nullable|date_format:H:i:s', 'check_out' => 'nullable|date_format:H:i:s', 'gps_data' => 'nullable|array', 'gps_data.check_in' => 'nullable|array', 'gps_data.check_in.latitude' => 'nullable|numeric', 'gps_data.check_in.longitude' => 'nullable|numeric', 'gps_data.check_out' => 'nullable|array', 'gps_data.check_out.latitude' => 'nullable|numeric', 'gps_data.check_out.longitude' => 'nullable|numeric', 'external_work' => 'nullable|array', 'external_work.location' => 'nullable|string|max:255', 'external_work.purpose' => 'nullable|string|max:500', 'work_minutes' => 'nullable|integer|min:0', 'overtime_minutes' => 'nullable|integer|min:0', 'late_minutes' => 'nullable|integer|min:0', 'early_leave_minutes' => 'nullable|integer|min:0', 'vacation_type' => 'nullable|string|max:50', ]; } public function messages(): array { return [ 'user_id.required' => __('validation.required', ['attribute' => '사용자']), 'base_date.required' => __('validation.required', ['attribute' => '기준일']), ]; } }