From 31d1a798f42823948f510db2b977ab8469cc181b Mon Sep 17 00:00:00 2001 From: Andrei Prigorshnev Date: Wed, 14 Dec 2022 12:42:17 +0400 Subject: [PATCH] FEATURE: do not suggest users on vacation (#395) --- .../discourse_assign/assign_controller.rb | 42 ++++++++++++------- lib/discourse_calendar.rb | 7 ++++ plugin.rb | 1 + spec/requests/assign_controller_spec.rb | 37 +++++++++++++++- 4 files changed, 70 insertions(+), 17 deletions(-) create mode 100644 lib/discourse_calendar.rb diff --git a/app/controllers/discourse_assign/assign_controller.rb b/app/controllers/discourse_assign/assign_controller.rb index 4bd5e12..3678e10 100644 --- a/app/controllers/discourse_assign/assign_controller.rb +++ b/app/controllers/discourse_assign/assign_controller.rb @@ -6,22 +6,7 @@ module DiscourseAssign before_action :ensure_logged_in, :ensure_assign_allowed def suggestions - users = [current_user] - users += - User - .where("users.id <> ?", current_user.id) - .joins(<<~SQL) - JOIN( - SELECT assigned_to_id user_id, MAX(created_at) last_assigned - FROM assignments - WHERE assignments.assigned_to_type = 'User' - GROUP BY assigned_to_id - HAVING COUNT(*) < #{SiteSetting.max_assigned_topics} - ) as X ON X.user_id = users.id - SQL - .assign_allowed - .order("X.last_assigned DESC") - .limit(6) + users = [current_user, *recent_assignees] render json: { assign_allowed_on_groups: @@ -279,5 +264,30 @@ module DiscourseAssign def user_menu_limit UsersController::USER_MENU_LIST_LIMIT end + + def recent_assignees + User + .where("users.id <> ?", current_user.id) + .joins(<<~SQL) + JOIN( + SELECT assigned_to_id user_id, MAX(created_at) last_assigned + FROM assignments + WHERE assignments.assigned_to_type = 'User' + GROUP BY assigned_to_id + HAVING COUNT(*) < #{SiteSetting.max_assigned_topics} + ) as X ON X.user_id = users.id + SQL + .joins(<<~SQL) + LEFT JOIN( + SELECT DISTINCT ON (user_id) name, user_id + FROM user_custom_fields + WHERE name = '#{DiscourseCalendar::HOLIDAY_CUSTOM_FIELD}' + ) AS ucf on ucf.user_id = users.id + SQL + .where("ucf.name is NULL") + .assign_allowed + .order("X.last_assigned DESC") + .limit(6) + end end end diff --git a/lib/discourse_calendar.rb b/lib/discourse_calendar.rb new file mode 100644 index 0000000..3e7f36f --- /dev/null +++ b/lib/discourse_calendar.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module DiscourseAssign + module DiscourseCalendar + HOLIDAY_CUSTOM_FIELD ||= 'on_holiday' + end +end diff --git a/plugin.rb b/plugin.rb index 29b62ff..d8eeb02 100644 --- a/plugin.rb +++ b/plugin.rb @@ -17,6 +17,7 @@ register_asset "stylesheets/mobile/assigns.scss", :mobile load File.expand_path("../lib/discourse_assign/engine.rb", __FILE__) load File.expand_path("../lib/discourse_assign/helpers.rb", __FILE__) load File.expand_path("../lib/validators/assign_statuses_validator.rb", __FILE__) +load File.expand_path("../lib/discourse_calendar.rb", __FILE__) Discourse::Application.routes.append do mount ::DiscourseAssign::Engine, at: "/assign" diff --git a/spec/requests/assign_controller_spec.rb b/spec/requests/assign_controller_spec.rb index 6f2d840..d36b4cf 100644 --- a/spec/requests/assign_controller_spec.rb +++ b/spec/requests/assign_controller_spec.rb @@ -94,11 +94,39 @@ RSpec.describe DiscourseAssign::AssignController do describe "#suggestions" do before do - SiteSetting.max_assigned_topics = 1 sign_in(user) end + it "suggests the current user + the last 6 previously assigned users" do + assignees = 10.times.map { |_| assign_user_to_post.username } + + get "/assign/suggestions.json" + + suggestions = response.parsed_body["suggestions"].map { |u| u["username"] } + expect(suggestions).to contain_exactly(user.username, *assignees[4..9]) + end + + it "doesn't suggest users on holiday" do + user_on_vacation = assign_user_to_post + user_on_vacation.upsert_custom_fields(DiscourseAssign::DiscourseCalendar::HOLIDAY_CUSTOM_FIELD => "t") + + get "/assign/suggestions.json" + + suggestions = response.parsed_body["suggestions"].map { |u| u["username"] } + expect(suggestions).to_not include(user_on_vacation.username) + end + + it "suggests the current user even if they're on holiday" do + user.upsert_custom_fields(DiscourseAssign::DiscourseCalendar::HOLIDAY_CUSTOM_FIELD => "t") + + get "/assign/suggestions.json" + + suggestions = response.parsed_body["suggestions"].map { |u| u["username"] } + expect(suggestions).to include(user.username) + end + it "excludes other users from the suggestions when they already reached the max assigns limit" do + SiteSetting.max_assigned_topics = 1 another_admin = Fabricate(:admin, groups: [default_allowed_group]) Assigner.new(post.topic, user).assign(another_admin) @@ -107,6 +135,13 @@ RSpec.describe DiscourseAssign::AssignController do expect(suggestions).to contain_exactly(user.username) end + + def assign_user_to_post + assignee = Fabricate(:user, groups: [default_allowed_group]) + post = Fabricate(:post) + Assigner.new(post.topic, user).assign(assignee) + assignee + end end describe "#assign" do