diff --git a/lib/tasks/consul.rake b/lib/tasks/consul.rake index a43bdaaf6..9ad01c340 100644 --- a/lib/tasks/consul.rake +++ b/lib/tasks/consul.rake @@ -3,8 +3,10 @@ namespace :consul do task execute_release_tasks: ["settings:rename_setting_keys", "settings:add_new_settings", "cache:clear", - "execute_release_2.3.0_tasks"] + "execute_release_2.4.0_tasks"] - desc "Runs tasks needed to upgrade from 2.2.2 to 2.3.0" - task "execute_release_2.3.0_tasks": [] + desc "Runs tasks needed to upgrade from 2.3.1 to 2.4.0" + task "execute_release_2.4.0_tasks": [ + "polls:remove_duplicate_partial_results" + ] end diff --git a/lib/tasks/polls.rake b/lib/tasks/polls.rake index a3ce11e4b..95cfe5799 100644 --- a/lib/tasks/polls.rake +++ b/lib/tasks/polls.rake @@ -107,4 +107,44 @@ namespace :polls do end end end + + desc "Removes duplicate poll partial results" + task remove_duplicate_partial_results: :environment do + logger = ApplicationLogger.new + duplicate_records_logger = DuplicateRecordsLogger.new + + logger.info "Removing duplicate partial results in polls" + + Tenant.run_on_each do + duplicate_ids = Poll::PartialResult.where(option_id: nil) + .select(:question_id, :booth_assignment_id, :date, :answer) + .group(:question_id, :booth_assignment_id, :date, :answer) + .having("count(*) > 1") + .pluck(:question_id, :booth_assignment_id, :date, :answer) + + duplicate_ids.each do |question_id, booth_assignment_id, date, answer| + partial_results = Poll::PartialResult.where( + question_id: question_id, + booth_assignment_id: booth_assignment_id, + date: date, + answer: answer, + option_id: nil + ) + + partial_results.excluding(partial_results.first).each do |partial_result| + partial_result.delete + + tenant_info = " on tenant #{Tenant.current_schema}" unless Tenant.default? + log_message = "Deleted duplicate record with ID #{partial_result.id} " \ + "from the #{Poll::PartialResult.table_name} table " \ + "with question_id #{question_id}, " \ + "booth_assignment_id #{booth_assignment_id}, " \ + "date #{date} " \ + "and answer #{answer}" + tenant_info.to_s + logger.info(log_message) + duplicate_records_logger.info(log_message) + end + end + end + end end diff --git a/spec/lib/tasks/polls_spec.rb b/spec/lib/tasks/polls_spec.rb index 06f40b979..af035e50f 100644 --- a/spec/lib/tasks/polls_spec.rb +++ b/spec/lib/tasks/polls_spec.rb @@ -223,4 +223,88 @@ describe "polls tasks" do end end end + + describe "polls:remove_duplicate_partial_results" do + before { Rake::Task["polls:remove_duplicate_partial_results"].reenable } + + let(:booth_assignment) { create(:poll_booth_assignment) } + let(:other_booth_assignment) { create(:poll_booth_assignment) } + + it "removes duplicate partial results" do + question = create(:poll_question_multiple, :abcde, poll: poll, max_votes: 4) + + result_attributes = { + question_id: question.id, + booth_assignment_id: booth_assignment.id, + date: Date.current, + answer: "Answer A", + option_id: nil + } + other_result_attributes = result_attributes.merge(answer: "Answer B") + + result = create(:poll_partial_result, result_attributes) + other_result = create(:poll_partial_result, other_result_attributes) + other_booth_result = create(:poll_partial_result, + result_attributes.merge(booth_assignment_id: other_booth_assignment.id)) + + 2.times { insert(:poll_partial_result, result_attributes) } + insert(:poll_partial_result, other_result_attributes) + insert(:poll_partial_result, result_attributes.merge(booth_assignment_id: other_booth_assignment.id)) + + expect(Poll::PartialResult.count).to eq 7 + + Rake.application.invoke_task("polls:remove_duplicate_partial_results") + + expect(Poll::PartialResult.count).to eq 3 + expect(Poll::PartialResult.all).to match_array [result, other_result, other_booth_result] + end + + it "does not remove partial results with the same text and different options" do + question = create(:poll_question_multiple, :abcde, max_votes: 4) + option_a = question.question_options.find_by(title: "Answer A") + option_b = question.question_options.find_by(title: "Answer B") + + result_attributes = { + question: question, + booth_assignment_id: booth_assignment.id, + date: Date.current, + answer: "Answer A" + } + create(:poll_partial_result, result_attributes.merge(option: option_a)) + insert(:poll_partial_result, result_attributes.merge(option_id: option_b.id)) + + expect(Poll::PartialResult.count).to eq 2 + + Rake.application.invoke_task("polls:remove_duplicate_partial_results") + + expect(Poll::PartialResult.count).to eq 2 + end + + it "removes duplicate partial results on tenants" do + create(:tenant, schema: "partial_results") + + Tenant.switch("partial_results") do + question = create(:poll_question_multiple, :abc) + booth_assignment = create(:poll_booth_assignment) + + result_attributes = { + question_id: question.id, + booth_assignment_id: booth_assignment.id, + date: Date.current, + answer: "Answer A", + option_id: nil + } + create(:poll_partial_result, result_attributes) + insert(:poll_partial_result, result_attributes) + + expect(Poll::PartialResult.count).to eq 2 + end + + Rake.application.invoke_task("polls:remove_duplicate_partial_results") + + Tenant.switch("partial_results") do + expect(Poll::PartialResult.count).to eq 1 + end + end + end end