Skip to content

Commit

Permalink
FEATURE: change status on unsolve & fix assign changes (#289)
Browse files Browse the repository at this point in the history
* FEATURE: change status on unsolve & fix assign changes

When a topic is unsolved, it should have an option,
defined in the settings, to change its status to that state.

Fix assign changes when a topic was solved, previously it was
changing the assignee.

* DEV: Change names in tests and remove comments

* DEV: Update change status on solve implementation

Update tests to verify that the change status on solve feature is working as expected.
Change the implementation to loop throught the topic assignments and update the status.

* DEV: address review feedback
  • Loading branch information
Grubba27 committed May 8, 2024
1 parent e405ef1 commit 9db72ef
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 14 deletions.
1 change: 1 addition & 0 deletions config/locales/server.en.yml
Expand Up @@ -13,6 +13,7 @@ en:
notify_on_staff_accept_solved: "Send notification to the topic creator when a post is marked as solution by a staff."
ignore_solved_topics_in_assigned_reminder: "Prevent assigned reminder from including solved topics. only relevant when discourse-assign."
assignment_status_on_solve: "When a topic is solved update all assignments to this status"
assignment_status_on_unsolve: "When a topic is unsolved update all assignments to this status"
disable_solved_education_message: "Disable education message for solved topics."
accept_solutions_topic_author: "Allow the topic author to accept a solution."
solved_add_schema_markup: "Add QAPage schema markup to HTML."
Expand Down
3 changes: 3 additions & 0 deletions config/settings.yml
Expand Up @@ -37,6 +37,9 @@ discourse_solved:
assignment_status_on_solve:
type: string
default: ""
assignment_status_on_unsolve:
type: string
default: ""
disable_solved_education_message:
default: false
accept_solutions_topic_author:
Expand Down
43 changes: 29 additions & 14 deletions plugin.rb
Expand Up @@ -303,7 +303,7 @@ def self.skip_db?
if SiteSetting.prioritize_solved_topics_in_search
condition = <<~SQL
EXISTS (
SELECT 1
SELECT 1
FROM topic_custom_fields
WHERE topic_id = topics.id
AND name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}'
Expand Down Expand Up @@ -336,7 +336,7 @@ def self.skip_db?
topics.id IN (
SELECT topic_id
FROM topic_custom_fields
WHERE name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}'
WHERE name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}'
AND value IS NOT NULL
)
SQL
Expand All @@ -349,7 +349,7 @@ def self.skip_db?
topics.id NOT IN (
SELECT topic_id
FROM topic_custom_fields
WHERE name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}'
WHERE name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}'
AND value IS NOT NULL
)
SQL
Expand All @@ -361,15 +361,15 @@ def self.skip_db?
topics.id IN (
SELECT t.id
FROM topics t
JOIN category_custom_fields cc
JOIN category_custom_fields cc
ON t.category_id = cc.category_id
AND cc.name = '#{::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD}'
AND cc.name = '#{::DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD}'
AND cc.value = 'true'
)
OR
)
OR
topics.id IN (
SELECT topic_id
FROM topic_tags
SELECT topic_id
FROM topic_tags
WHERE tag_id IN (?)
)
SQL
Expand Down Expand Up @@ -404,7 +404,7 @@ def self.skip_db?
->(r) do
sql = <<~SQL
NOT EXISTS (
SELECT 1
SELECT 1
FROM topic_custom_fields
WHERE topic_id = topics.id
AND name = '#{::DiscourseSolved::ACCEPTED_ANSWER_POST_ID_CUSTOM_FIELD}'
Expand Down Expand Up @@ -591,10 +591,25 @@ def self.skip_db?
if defined?(DiscourseAssign)
on(:accepted_solution) do |post|
next if SiteSetting.assignment_status_on_solve.blank?
Assigner.new(post.topic, post.acting_user).assign(
post.acting_user,
status: SiteSetting.assignment_status_on_solve,
)
assignments = Assignment.includes(:target).where(topic: post.topic)
assignments.each do |assignment|
assigned_user = User.find_by(id: assignment.assigned_to_id)
Assigner.new(assignment.target, assigned_user).assign(
assigned_user,
status: SiteSetting.assignment_status_on_solve,
)
end
end
on(:unaccepted_solution) do |post|
next if SiteSetting.assignment_status_on_unsolve.blank?
assignments = Assignment.includes(:target).where(topic: post.topic)
assignments.each do |assignment|
assigned_user = User.find_by(id: assignment.assigned_to_id)
Assigner.new(assignment.target, assigned_user).assign(
assigned_user,
status: SiteSetting.assignment_status_on_unsolve,
)
end
end
end
end
45 changes: 45 additions & 0 deletions spec/integration/solved_spec.rb
Expand Up @@ -439,6 +439,7 @@
SiteSetting.assign_allowed_on_groups = "#{group.id}"
SiteSetting.assigns_public = true
SiteSetting.assignment_status_on_solve = "Done"
SiteSetting.assignment_status_on_unsolve = "New"
SiteSetting.ignore_solved_topics_in_assigned_reminder = false
group.add(p1.acting_user)
group.add(user)
Expand All @@ -458,6 +459,50 @@
expect(p1.topic.assignment.reload.status).to eq("Done")
end

it "update all assignments to this status when a post is unaccepted" do
assigner = Assigner.new(p1.topic, user)
result = assigner.assign(user)
expect(result[:success]).to eq(true)

DiscourseSolved.accept_answer!(p1, user)

expect(p1.reload.topic.assignment.reload.status).to eq("Done")

DiscourseSolved.unaccept_answer!(p1)

expect(p1.reload.custom_fields["is_accepted_answer"]).to eq(nil)
expect(p1.reload.topic.assignment.reload.status).to eq("New")
end

it "does not update the assignee when a post is accepted" do
user_1 = Fabricate(:user)
user_2 = Fabricate(:user)
user_3 = Fabricate(:user)
group.add(user_1)
group.add(user_2)
group.add(user_3)

topic_question = Fabricate(:topic, user: user_1)
post_question = Fabricate(:post, topic: topic_question, user: user_1)

user_2_response = Fabricate(:post, topic: topic_question, user: user_2)
assigner = Assigner.new(topic_question, user_2)
result = assigner.assign(user_2)
expect(result[:success]).to eq(true)

post_response = Fabricate(:post, topic: topic_question, user: user_3)
Assigner.new(post_response, user_3).assign(user_3)

DiscourseSolved.accept_answer!(post_response, user_1)

expect(topic_question.assignment.assigned_to_id).to eq(user_2.id)
expect(post_response.assignment.assigned_to_id).to eq(user_3.id)
DiscourseSolved.unaccept_answer!(post_response)

expect(topic_question.assignment.assigned_to_id).to eq(user_2.id)
expect(post_response.assignment.assigned_to_id).to eq(user_3.id)
end

describe "assigned topic reminder"
it "excludes solved topics when ignore_solved_topics_in_assigned_reminder is false" do
other_topic = Fabricate(:topic, title: "Topic that should be there")
Expand Down

0 comments on commit 9db72ef

Please sign in to comment.