From 039ca40bac8e9e22c52a3894aa4f6270ec6048bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guitaut?= Date: Thu, 16 Nov 2023 16:09:08 +0100 Subject: [PATCH] WIP: refactor --- lib/random_assign_utils.rb | 174 ++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 69 deletions(-) diff --git a/lib/random_assign_utils.rb b/lib/random_assign_utils.rb index fbb95a35..78d781a8 100644 --- a/lib/random_assign_utils.rb +++ b/lib/random_assign_utils.rb @@ -29,84 +29,21 @@ def initialize(context, fields, automation) end def automation_script! - min_hours = fields.dig("minimum_time_between_assignments", "value").presence - if min_hours && - TopicCustomField - .where(name: "assigned_to_id", topic: topic) - .where("created_at < ?", min_hours.to_i.hours.ago) - .exists? - log_info("Topic(#{topic.id}) has already been assigned recently") - return - end - - assignable_user_ids = User.assign_allowed.pluck(:id) - users_on_holiday = - Set.new( - User.where( - id: UserCustomField.where(name: "on_holiday", value: "t").select(:user_id), - ).pluck(:id), - ) - - group_users = group.group_users.joins(:user) - if skip_new_users_for_days = fields.dig("skip_new_users_for_days", "value").presence - group_users = group_users.where("users.created_at < ?", skip_new_users_for_days.to_i.days.ago) - end - - group_users_ids = - group_users - .pluck("users.id") - .filter { |user_id| assignable_user_ids.include?(user_id) } - .reject { |user_id| users_on_holiday.include?(user_id) } - - return no_one! if group_users_ids.empty? - - max_recently_assigned_days = - (fields.dig("max_recently_assigned_days", "value").presence || 180).to_i.days.ago - last_assignees_ids = recently_assigned_users_ids(max_recently_assigned_days) - users_ids = group_users_ids - last_assignees_ids - if users_ids.blank? - min_recently_assigned_days = - (fields.dig("min_recently_assigned_days", "value").presence || 14).to_i.days.ago - recently_assigned_users_ids = recently_assigned_users_ids(min_recently_assigned_days) - users_ids = group_users_ids - recently_assigned_users_ids - end - - users_ids << last_assignees_ids.last if users_ids.blank? - - if fields.dig("in_working_hours", "value") - assign_to_user_id = users_ids.shuffle.detect { |user_id| in_working_hours?(user_id) } - end - assign_to_user_id ||= users_ids.sample - - assign_to = User.find(assign_to_user_id) - result = nil - if raw = fields.dig("post_template", "value").presence - post = - PostCreator.new( - Discourse.system_user, - raw: raw, - skip_validations: true, - topic_id: topic.id, - ).create! - - result = Assigner.new(post, Discourse.system_user).assign(assign_to) - - PostDestroyer.new(Discourse.system_user, post).destroy if !result[:success] - else - result = Assigner.new(topic, Discourse.system_user).assign(assign_to) - end - - no_one! if !result[:success] + return log_info("Topic(#{topic.id}) has already been assigned recently") if assigned_recently? + return no_one! unless assigned_user + assign_user! end def recently_assigned_users_ids(from) posts = Post + .select(:id) .joins(:user) .where(topic: topic, action_code: %w[assigned reassigned assigned_to_post]) .where("posts.created_at > ?", from) .order(created_at: :desc) - usernames = posts.map { _1.custom_fields[:action_code_who] }.uniq + usernames = + Post.custom_fields_for_ids(posts, [:action_code_who]).map { |_, v| v["action_code_who"] }.uniq User .where(username: usernames) .joins( @@ -135,6 +72,28 @@ def no_one! ) end + def assigned_user + @assigned_user ||= + begin + group_users_ids = group_users.pluck(:id) + return if group_users_ids.empty? + + last_assignees_ids = recently_assigned_users_ids(max_recently_assigned_days) + users_ids = group_users_ids - last_assignees_ids + if users_ids.blank? + recently_assigned_users_ids = recently_assigned_users_ids(min_recently_assigned_days) + users_ids = group_users_ids - recently_assigned_users_ids + end + users_ids << last_assignees_ids.last if users_ids.blank? + if fields.dig("in_working_hours", "value") + assign_to_user_id = users_ids.shuffle.detect { |user_id| in_working_hours?(user_id) } + end + assign_to_user_id ||= users_ids.sample + + User.find(assign_to_user_id) + end + end + def in_working_hours?(user_id) tzinfo = user_tzinfo(user_id) tztime = tzinfo.now @@ -158,4 +117,81 @@ def user_tzinfo(user_id) tzinfo end + + def min_hours + hours = fields.dig("minimum_time_between_assignments", "value").presence + return unless hours + hours.to_i.hours.ago + end + + def assigned_recently? + return unless min_hours + TopicCustomField + .where(name: "assigned_to_id", topic: topic) + .where("created_at < ?", min_hours) + .exists? + end + + def skip_new_users_for_days + days = fields.dig("skip_new_users_for_days", "value").presence + return unless days + days.to_i.days.ago + end + + def group_users + users = + group + .users + .where(id: User.assign_allowed.select(:id)) + .where.not( + id: + User + .joins(:_custom_fields) + .where(user_custom_fields: { name: "on_holiday", value: "t" }) + .select(:id), + ) + return users unless skip_new_users_for_days + users.where("users.created_at < ?", skip_new_users_for_days) + end + + def max_recently_assigned_days + @max_days ||= (fields.dig("max_recently_assigned_days", "value").presence || 180).to_i.days.ago + end + + def min_recently_assigned_days + @min_days ||= (fields.dig("min_recently_assigned_days", "value").presence || 14).to_i.days.ago + end + + def post_template + @post_template ||= fields.dig("post_template", "value").presence + end + + def create_post_template + post = + PostCreator.new( + Discourse.system_user, + raw: post_template, + skip_validations: true, + topic_id: topic.id, + ).create! + Assigner + .new(post, Discourse.system_user) + .assign(assigned_user) + .then do |result| + next if result[:success] + PostDestroyer.new(Discourse.system_user, post).destroy + no_one! + end + end + + def assign_user! + return create_post_template if post_template + Assigner + .new(topic, Discourse.system_user) + .assign(assigned_user) + .then do |result| + next if result[:success] + no_one! + end + end end