diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 46aa4a6..cc0751d 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -86,7 +86,13 @@ en: assignees_group: label: Assignees Group minimum_time_between_assignments: - label: Hours between assignments + label: Mininmum hours between assignments + min_recently_assigned_days: + label: Min recently assigned days + description: Defaults to 14 days. + max_recently_assigned_days: + label: Max recently assigned days + description: First attempt to exclude users assigned in the last `n` days. If no user left, fallbacks to `min_recently_assigned_days`. Defaults to 180 days. assigned_topic: label: Assigned Topic ID in_working_hours: diff --git a/lib/random_assign_utils.rb b/lib/random_assign_utils.rb index 0360e9d..68a8766 100644 --- a/lib/random_assign_utils.rb +++ b/lib/random_assign_utils.rb @@ -1,6 +1,16 @@ # frozen_string_literal: true class RandomAssignUtils + def self.recently_assigned_users_ids(topic_id, from) + posts = Post + .joins(:user) + .where(topic_id: topic_id, action_code: 'assigned') + .where('posts.created_at > ?', from) + .order(created_at: :desc) + usernames = Post.custom_fields_for_ids(posts, [:action_code_who]).map { |_, v| v['action_code_who'] }.uniq + User.where(username: usernames).limit(100).pluck(:id) + end + def self.user_tzinfo(user_id) timezone = UserOption.where(user_id: user_id).pluck(:timezone).first || "UTC" diff --git a/plugin.rb b/plugin.rb index 1634cb3..e3c4f53 100644 --- a/plugin.rb +++ b/plugin.rb @@ -701,6 +701,8 @@ after_initialize do field :assignees_group, component: :group field :assigned_topic, component: :text field :minimum_time_between_assignments, component: :text + field :max_recently_assigned_days, component: :text + field :min_recently_assigned_days, component: :text field :in_working_hours, component: :boolean version 1 @@ -719,7 +721,7 @@ after_initialize do 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') + min_hours = fields.dig('minimum_time_between_assignments', 'value').presence if min_hours && TopicCustomField .where(name: 'assigned_to_id', topic_id: topic_id) .where('created_at < ?', min_hours.to_i.hours.ago) @@ -747,23 +749,14 @@ after_initialize do 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 + last_assignees_ids = RandomAssignUtils.recently_assigned_users_ids( + topic_id, + (fields.dig('max_recently_assigned_days', 'value').presence || 180).to_i.days.ago + ) 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 + recently_assigned_users_ids = RandomAssignUtils.recently_assigned_users_ids(topic_id, (fields.dig('min_recently_assigned_days', 'value').presence || 14).to_i.days.ago) users_ids = group_users_ids - recently_assigned_users_ids end diff --git a/spec/lib/random_assign_utils_spec.rb b/spec/lib/random_assign_utils_spec.rb new file mode 100644 index 0000000..129d7ed --- /dev/null +++ b/spec/lib/random_assign_utils_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'rails_helper' +require_relative '../support/assign_allowed_group' +require 'random_assign_utils' + +describe RandomAssignUtils do + before do + SiteSetting.assign_enabled = true + end + + let(:post) { Fabricate(:post) } + + describe '.recently_assigned_users_ids' do + context 'no one has been assigned' do + it 'returns an empty array' do + assignees_ids = described_class.recently_assigned_users_ids(post.topic_id, 2.months.ago) + expect(assignees_ids).to eq([]) + end + end + + context 'users have been assigned' do + let(:admin) { Fabricate(:admin) } + let(:assign_allowed_group) { Group.find_by(name: 'staff') } + let(:user_1) { Fabricate(:user, groups: [assign_allowed_group]) } + let(:user_2) { Fabricate(:user, groups: [assign_allowed_group]) } + let(:user_3) { Fabricate(:user, groups: [assign_allowed_group]) } + + it 'returns the recently assigned user ids' do + freeze_time 1.months.ago do + Assigner.new(post.topic, admin).assign(user_1) + Assigner.new(post.topic, admin).assign(user_2) + end + + freeze_time 3.months.ago do + Assigner.new(post.topic, admin).assign(user_3) + end + + assignees_ids = described_class.recently_assigned_users_ids(post.topic_id, 2.months.ago) + + expect(assignees_ids).to contain_exactly(user_1.id, user_2.id) + end + end + end +end