FEATURE: improves random assign automation (#166)
- Makes a best attempt at being random and assigning people who haven’t been assigned for a long time - Uses timezones and holidays - Allows to define a minimum delay between assignments - Creates a post if no one is available
This commit is contained in:
parent
a8495e9d7a
commit
0046041e9e
|
@ -75,5 +75,7 @@ en:
|
||||||
fields:
|
fields:
|
||||||
assignees_group:
|
assignees_group:
|
||||||
label: Assignees Group
|
label: Assignees Group
|
||||||
|
minimum_time_between_assignments:
|
||||||
|
label: Hours between assignments
|
||||||
assigned_topic:
|
assigned_topic:
|
||||||
label: Assigned Topic ID
|
label: Assigned Topic ID
|
||||||
|
|
|
@ -66,3 +66,4 @@ en:
|
||||||
scriptables:
|
scriptables:
|
||||||
random_assign:
|
random_assign:
|
||||||
title: Random assign
|
title: Random assign
|
||||||
|
no_one: "Attempted randomly assign a member of @%{group}, but no one was available."
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RandomAssignUtils
|
||||||
|
def self.user_tzinfo(user_id)
|
||||||
|
timezone = UserOption.where(user_id: user_id).pluck(:timezone).first || "UTC"
|
||||||
|
|
||||||
|
tzinfo = nil
|
||||||
|
begin
|
||||||
|
tzinfo = ActiveSupport::TimeZone.find_tzinfo(timezone)
|
||||||
|
rescue TZInfo::InvalidTimezoneIdentifier
|
||||||
|
Rails.logger.warn("#{User.find_by(id: user_id)&.username} has the timezone #{timezone} set, we do not know how to parse it in Rails (assuming UTC)")
|
||||||
|
timezone = "UTC"
|
||||||
|
tzinfo = ActiveSupport::TimeZone.find_tzinfo(timezone)
|
||||||
|
end
|
||||||
|
|
||||||
|
tzinfo
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.no_one!(topic_id, group)
|
||||||
|
PostCreator.create!(
|
||||||
|
Discourse.system_user,
|
||||||
|
topic_id: topic_id,
|
||||||
|
raw: I18n.t("discourse_automation.scriptables.random_assign.no_one", group: group),
|
||||||
|
validate: false
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.in_working_hours?(user_id)
|
||||||
|
tzinfo = RandomAssignUtils.user_tzinfo(user_id)
|
||||||
|
tztime = tzinfo.now
|
||||||
|
|
||||||
|
!tztime.saturday? &&
|
||||||
|
!tztime.sunday? &&
|
||||||
|
tztime.hour > 7 &&
|
||||||
|
tztime.hour < 11
|
||||||
|
end
|
||||||
|
end
|
75
plugin.rb
75
plugin.rb
|
@ -539,9 +539,12 @@ after_initialize do
|
||||||
end
|
end
|
||||||
|
|
||||||
if defined?(DiscourseAutomation)
|
if defined?(DiscourseAutomation)
|
||||||
|
require 'random_assign_utils'
|
||||||
|
|
||||||
add_automation_scriptable('random_assign') do
|
add_automation_scriptable('random_assign') do
|
||||||
field :assignees_group, component: :group
|
field :assignees_group, component: :group
|
||||||
field :assigned_topic, component: :text
|
field :assigned_topic, component: :text
|
||||||
|
field :minimum_time_between_assignments, component: :text
|
||||||
|
|
||||||
version 1
|
version 1
|
||||||
|
|
||||||
|
@ -550,14 +553,76 @@ after_initialize do
|
||||||
script do |context, fields|
|
script do |context, fields|
|
||||||
next unless SiteSetting.assign_enabled?
|
next unless SiteSetting.assign_enabled?
|
||||||
|
|
||||||
next unless group_id = fields.dig('assignees_group', 'value')
|
|
||||||
next unless group = Group.find_by(id: group_id)
|
|
||||||
assign_to = group.group_users.order(Arel.sql('RANDOM()')).first.user
|
|
||||||
|
|
||||||
next unless topic_id = fields.dig('assigned_topic', 'value')
|
next unless topic_id = fields.dig('assigned_topic', 'value')
|
||||||
next unless topic = Topic.find_by(id: topic_id)
|
next unless topic = Topic.find_by(id: topic_id)
|
||||||
|
|
||||||
TopicAssigner.new(topic, Discourse.system_user).assign(assign_to)
|
next unless group_id = fields.dig('assignees_group', 'value')
|
||||||
|
next unless group = Group.find_by(id: group_id)
|
||||||
|
|
||||||
|
min_hours = (fields.dig('minimum_time_between_assignments', 'value') || 12).to_i
|
||||||
|
if TopicCustomField
|
||||||
|
.where(name: 'assigned_to_id', topic_id: topic_id)
|
||||||
|
.where('created_at < ?', min_hours.hours.ago)
|
||||||
|
.exists?
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
users_on_holiday = Set.new(
|
||||||
|
User
|
||||||
|
.where(id:
|
||||||
|
UserCustomField
|
||||||
|
.where(name: 'on_holiday', value: 't')
|
||||||
|
.pluck(:user_id)
|
||||||
|
).pluck(:id)
|
||||||
|
)
|
||||||
|
|
||||||
|
group_users_ids = group
|
||||||
|
.group_users
|
||||||
|
.joins(:user)
|
||||||
|
.pluck('users.id')
|
||||||
|
.reject { |user_id| users_on_holiday.include?(user_id) }
|
||||||
|
|
||||||
|
if group_users_ids.empty?
|
||||||
|
RandomAssignUtils.no_one!(topic_id, group.name)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
last_assignees_ids = UserAction
|
||||||
|
.joins(:user)
|
||||||
|
.where(action_type: UserAction::ASSIGNED, target_topic_id: topic_id)
|
||||||
|
.where('user_actions.created_at > ?', 6.months.ago)
|
||||||
|
.order(created_at: :desc)
|
||||||
|
.limit(group_users_ids.length)
|
||||||
|
.pluck('users.id')
|
||||||
|
.uniq
|
||||||
|
|
||||||
|
users_ids = group_users_ids - last_assignees_ids
|
||||||
|
if users_ids.blank?
|
||||||
|
recently_assigned_users_ids = UserAction
|
||||||
|
.joins(:user)
|
||||||
|
.where(action_type: UserAction::ASSIGNED, target_topic_id: topic_id)
|
||||||
|
.where('user_actions.created_at < ?', 2.weeks.ago)
|
||||||
|
.pluck('users.id')
|
||||||
|
.uniq
|
||||||
|
users_ids = group_users_ids - recently_assigned_users_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
if users_ids.blank?
|
||||||
|
RandomAssignUtils.no_one!(topic_id, group.name)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
assign_to_user_id = users_ids.shuffle.find do |user_id|
|
||||||
|
RandomAssignUtils.in_working_hours?(user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
if assign_to_user_id.blank?
|
||||||
|
RandomAssignUtils.no_one!(topic_id, group.name)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
assign_to = User.find_by(id: assign_to_user_id)
|
||||||
|
assign_to && TopicAssigner.new(topic, Discourse.system_user).assign(assign_to)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue