diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 64adbaddf..fbc03f467 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -61,6 +61,7 @@ class Budget before_save :calculate_confidence_score before_validation :set_responsible_name before_validation :set_denormalized_ids + after_save :check_for_reclassification def self.filter_params(params) params.select{|x,_| %w{heading_id group_id administrator_id tag_name valuator_id}.include? x.to_s } @@ -242,6 +243,25 @@ class Budget investments end + def check_for_reclassification + if reclassified? + log_reclassification + remove_reclassified_votes + end + end + + def reclassified? + budget.balloting? && heading_id_changed? + end + + def log_reclassification + self.previous_heading_id = self.heading_id_was + end + + def remove_reclassified_votes + Budget::Ballot::Line.where(investment: self).destroy_all + end + private def set_denormalized_ids diff --git a/db/migrate/20170513110025_add_previous_heading_id_to_investments.rb b/db/migrate/20170513110025_add_previous_heading_id_to_investments.rb new file mode 100644 index 000000000..878799712 --- /dev/null +++ b/db/migrate/20170513110025_add_previous_heading_id_to_investments.rb @@ -0,0 +1,5 @@ +class AddPreviousHeadingIdToInvestments < ActiveRecord::Migration + def change + add_column :budget_investments, :previous_heading_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index a56818609..b525da1d1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170503163330) do +ActiveRecord::Schema.define(version: 20170513110025) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -146,6 +146,7 @@ ActiveRecord::Schema.define(version: 20170503163330) do t.string "organization_name" t.datetime "unfeasible_email_sent_at" t.integer "ballot_lines_count", default: 0 + t.integer "previous_heading_id" end add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree diff --git a/spec/features/budgets/investments_spec.rb b/spec/features/budgets/investments_spec.rb index 37ab50fda..ca5427820 100644 --- a/spec/features/budgets/investments_spec.rb +++ b/spec/features/budgets/investments_spec.rb @@ -652,5 +652,25 @@ feature 'Budget Investments' do expect(page).to have_current_path(expected_path) end + scenario "Reclassification" do + user = create(:user, :level_two) + investment = create(:budget_investment, :selected, heading: heading) + heading2 = create(:budget_heading, group: group) + + ballot = create(:budget_ballot, user: user, budget: budget) + ballot.investments << investment + + login_as(user) + visit budget_ballot_path(budget) + + expect(page).to have_content("You have voted one investment") + + investment.heading = heading2 + investment.save + + visit budget_ballot_path(budget) + + expect(page).to have_content("You have voted 0 investment") + end end end diff --git a/spec/models/budget/investment_spec.rb b/spec/models/budget/investment_spec.rb index 2c5f03738..6486070bf 100644 --- a/spec/models/budget/investment_spec.rb +++ b/spec/models/budget/investment_spec.rb @@ -674,4 +674,113 @@ describe Budget::Investment do end + describe "Reclassification" do + + let(:budget) { create(:budget, phase: "balloting") } + let(:group) { create(:budget_group, budget: budget) } + let(:heading1) { create(:budget_heading, group: group) } + let(:heading2) { create(:budget_heading, group: group) } + + describe "reclassified?" do + + it "returns true if budget is in balloting phase and heading has changed" do + investment = create(:budget_investment, heading: heading1) + investment.heading = heading2 + + expect(investment.reclassified?).to eq(true) + end + + it "returns false if heading has not changed" do + investment = create(:budget_investment) + investment.heading = investment.heading + + expect(investment.reclassified?).to eq(false) + end + + it "returns false if budget is not balloting phase" do + Budget::PHASES.reject {|phase| phase == "balloting"}.each do |phase| + budget.update(phase: phase) + investment = create(:budget_investment, budget: budget) + + investment.heading = heading2 + + expect(investment.reclassified?).to eq(false) + end + end + + end + + describe "log_reclassification" do + + it "stores the previous heading before being reclassified" do + investment = create(:budget_investment, heading: heading1) + + investment.heading = heading2 + investment.save + + expect(investment.heading_id).to eq(heading2.id) + expect(investment.previous_heading_id).to eq(heading1.id) + end + + end + + describe "remove_reclassified_votes" do + + it "removes votes from invesment" do + investment = create(:budget_investment, :selected, heading: heading1) + + 3.times do + ballot = create(:budget_ballot, budget: budget) + ballot.investments << investment + end + + expect(investment.ballot_lines_count).to eq(3) + + investment.heading = heading2 + investment.remove_reclassified_votes + + investment.reload + expect(investment.ballot_lines_count).to eq(0) + end + + end + + describe "check_for_reclassification" do + + it "removes votes if an investment has been reclassified" do + investment = create(:budget_investment, :selected, heading: heading1) + + 3.times do + ballot = create(:budget_ballot, budget: budget) + ballot.investments << investment + end + + expect(investment.ballot_lines_count).to eq(3) + + investment.heading = heading2 + investment.save + investment.reload + + expect(investment.ballot_lines_count).to eq(0) + end + + it "does not remove votes if the investment has not been reclassifed" do + investment = create(:budget_investment, :selected, heading: heading1) + + 3.times do + ballot = create(:budget_ballot, budget: budget) + ballot.investments << investment + end + + expect(investment.ballot_lines_count).to eq(3) + + investment.save + investment.reload + + expect(investment.ballot_lines_count).to eq(3) + end + + end + + end end