From bdffb9765e8079c86fc16cda312b201f2ad3c50a Mon Sep 17 00:00:00 2001 From: rgarcia Date: Wed, 21 Mar 2018 19:43:40 +0100 Subject: [PATCH] Allow voting in multiple headings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have the option of voting in multiple headings per group, the method of voting in a “different heading assigned” has become deprecated and thus removed --- app/models/budget/investment.rb | 8 +-- app/views/budgets/investments/_votes.html.erb | 3 +- config/locales/en/admin.yml | 1 + config/locales/en/budgets.yml | 4 +- config/locales/es/admin.yml | 1 + config/locales/es/budgets.yml | 4 +- spec/features/budgets/votes_spec.rb | 69 +++++++++++++++++++ spec/models/budget/investment_spec.rb | 43 ++++++++++++ 8 files changed, 126 insertions(+), 7 deletions(-) diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index dff2dd2e0..28cc5bded 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -231,12 +231,12 @@ class Budget end def valid_heading?(user) - !different_heading_assigned?(user) + voted_in?([heading.id], user) || + can_vote_in_another_heading?(user) end - def different_heading_assigned?(user) - other_heading_ids = group.heading_ids - [heading.id] - voted_in?(other_heading_ids, user) + def can_vote_in_another_heading?(user) + headings_voted_by_user(user).count < group.max_votable_headings end def voted_in?(heading_ids, user) diff --git a/app/views/budgets/investments/_votes.html.erb b/app/views/budgets/investments/_votes.html.erb index 035ff5edb..421905038 100644 --- a/app/views/budgets/investments/_votes.html.erb +++ b/app/views/budgets/investments/_votes.html.erb @@ -19,7 +19,7 @@ title: t('budgets.investments.investment.support_title'), method: "post", remote: (current_user && current_user.voted_in_group?(investment.group) ? true : false), - data: (current_user && current_user.voted_in_group?(investment.group) ? nil : { confirm: t('budgets.investments.investment.confirm_group')} ), + data: (current_user && current_user.voted_in_group?(investment.group) ? nil : { confirm: t('budgets.investments.investment.confirm_group', count: investment.group.max_votable_headings)} ), "aria-hidden" => css_for_aria_hidden(reason) do %> <%= t("budgets.investments.investment.give_support") %> <% end %> @@ -31,6 +31,7 @@

<%= t("votes.budget_investments.#{reason}", + count: investment.group.max_votable_headings, verify_account: link_to(t("votes.verify_account"), verification_path), signin: link_to(t("votes.signin"), new_user_session_path), signup: link_to(t("votes.signup"), new_user_registration_path) diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index baa678996..ad03c3a13 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -119,6 +119,7 @@ en: table_amount: Amount table_population: Population population_info: "Budget Heading population field is used for Statistic purposes at the end of the Budget to show for each Heading that represents an area with population what percentage voted. The field is optional so you can leave it empty if it doesn't apply." + max_votable_headings: "Maxium number of headings in which a user can vote" winners: calculate: Calculate Winner Investments calculated: Winners being calculated, it may take a minute. diff --git a/config/locales/en/budgets.yml b/config/locales/en/budgets.yml index b0b393b42..983262160 100644 --- a/config/locales/en/budgets.yml +++ b/config/locales/en/budgets.yml @@ -130,7 +130,9 @@ en: already_added: You have already added this investment project already_supported: You have already supported this investment project. Share it! support_title: Support this project - confirm_group: "You can only support investments in one heading. If you continue you cannot change your decision. Are you sure?" + confirm_group: + one: "You can only support investments in %{count} heading. If you continue you cannot change your decision. Are you sure?" + other: "You can only support investments in %{count} headings. If you continue you cannot change your decision. Are you sure?" supports: one: 1 support other: "%{count} supports" diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index 9fb9fae63..1cbbf2d14 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -119,6 +119,7 @@ es: table_amount: Cantidad table_population: Población population_info: "El campo población de las partidas presupuestarias se usa con fines estadísticos únicamente, con el objetivo de mostrar el porcentaje de votos habidos en cada partida que represente un área con población. Es un campo opcional, así que puedes dejarlo en blanco si no aplica." + max_votable_headings: "Máximo número de partidas en que un usuario puede votar" winners: calculate: Calcular propuestas ganadoras calculated: Calculando ganadoras, puede tardar un minuto. diff --git a/config/locales/es/budgets.yml b/config/locales/es/budgets.yml index ab1a1e4ac..0b940f2de 100644 --- a/config/locales/es/budgets.yml +++ b/config/locales/es/budgets.yml @@ -130,7 +130,9 @@ es: already_added: Ya has añadido este proyecto de gasto already_supported: Ya has apoyado este proyecto de gasto. ¡Compártelo! support_title: Apoyar este proyecto - confirm_group: "Sólo puedes apoyar proyectos de una partida. Si sigues adelante no podrás cambiar esta decisión. ¿Estás seguro?" + confirm_group: + one: "Sólo puedes apoyar proyectos de %{count} partida. Si sigues adelante no podrás cambiar esta decisión. ¿Estás seguro?" + other: "Sólo puedes apoyar proyectos de %{count} partidas. Si sigues adelante no podrás cambiar esta decisión. ¿Estás seguro?" supports: zero: Sin apoyos one: 1 apoyo diff --git a/spec/features/budgets/votes_spec.rb b/spec/features/budgets/votes_spec.rb index 6da622b44..5a56af51b 100644 --- a/spec/features/budgets/votes_spec.rb +++ b/spec/features/budgets/votes_spec.rb @@ -103,5 +103,74 @@ feature 'Votes' do expect(page).not_to have_css("budget_investment_#{investment.id}_votes") end end + + context "Voting in multiple headings of a single group" do + + let(:new_york) { heading } + let(:san_francisco) { create(:budget_heading, group: group) } + let(:third_heading) { create(:budget_heading, group: group) } + + let!(:new_york_investment) { create(:budget_investment, heading: new_york) } + let!(:san_francisco_investment) { create(:budget_investment, heading: san_francisco) } + let!(:third_heading_investment) { create(:budget_investment, heading: third_heading) } + + background do + group.update(max_votable_headings: 2) + end + + scenario "From Index", :js do + visit budget_investments_path(budget, heading_id: new_york.id) + + within("#budget_investment_#{new_york_investment.id}") do + find('.in-favor a').click + + expect(page).to have_content "1 support" + expect(page).to have_content "You have already supported this investment project. Share it!" + end + + visit budget_investments_path(budget, heading_id: san_francisco.id) + + within("#budget_investment_#{san_francisco_investment.id}") do + find('.in-favor a').click + + expect(page).to have_content "1 support" + expect(page).to have_content "You have already supported this investment project. Share it!" + end + + visit budget_investments_path(budget, heading_id: third_heading.id) + + within("#budget_investment_#{third_heading_investment.id}") do + find('.in-favor a').click + + expect(page).to have_content "You can only support investment projects in 2 districts" + + expect(page).to_not have_content "1 support" + expect(page).to_not have_content "You have already supported this investment project. Share it!" + end + end + + scenario "From show", :js do + visit budget_investment_path(budget, new_york_investment) + + find('.in-favor a').click + expect(page).to have_content "1 support" + expect(page).to have_content "You have already supported this investment project. Share it!" + + visit budget_investment_path(budget, san_francisco_investment) + + find('.in-favor a').click + expect(page).to have_content "1 support" + expect(page).to have_content "You have already supported this investment project. Share it!" + + visit budget_investment_path(budget, third_heading_investment) + + find('.in-favor a').click + expect(page).to have_content "You can only support investment projects in 2 districts" + + expect(page).to_not have_content "1 support" + expect(page).to_not have_content "You have already supported this investment project. Share it!" + end + + end end end diff --git a/spec/models/budget/investment_spec.rb b/spec/models/budget/investment_spec.rb index b8b3d423b..73bd46c5d 100644 --- a/spec/models/budget/investment_spec.rb +++ b/spec/models/budget/investment_spec.rb @@ -589,6 +589,20 @@ describe Budget::Investment do expect(salamanca_investment.valid_heading?(user)).to eq(false) end + it "accepts votes in multiple headings of the same group" do + group.update(max_votable_headings: 2) + + carabanchel = create(:budget_heading, group: group) + salamanca = create(:budget_heading, group: group) + + carabanchel_investment = create(:budget_investment, heading: carabanchel) + salamanca_investment = create(:budget_investment, heading: salamanca) + + create(:vote, votable: carabanchel_investment, voter: user) + + expect(salamanca_investment.valid_heading?(user)).to eq(true) + end + it "allows votes in a group with a single heading" do all_city_investment = create(:budget_investment, heading: heading) expect(all_city_investment.valid_heading?(user)).to eq(true) @@ -627,6 +641,35 @@ describe Budget::Investment do expect(carabanchel_investment.valid_heading?(user)).to eq(true) end + + describe "#can_vote_in_another_heading?" do + + let(:districts) { create(:budget_group, budget: budget) } + let(:carabanchel) { create(:budget_heading, group: districts) } + let(:salamanca) { create(:budget_heading, group: districts) } + let(:latina) { create(:budget_heading, group: districts) } + + let(:carabanchel_investment) { create(:budget_investment, heading: carabanchel) } + let(:salamanca_investment) { create(:budget_investment, heading: salamanca) } + let(:latina_investment) { create(:budget_investment, heading: latina) } + + it "returns true if the user has voted in less headings than the maximum" do + districts.update(max_votable_headings: 2) + + create(:vote, votable: carabanchel_investment, voter: user) + + expect(salamanca_investment.can_vote_in_another_heading?(user)).to eq(true) + end + + it "returns false if the user has already voted in the maximum number of headings" do + districts.update(max_votable_headings: 2) + + create(:vote, votable: carabanchel_investment, voter: user) + create(:vote, votable: salamanca_investment, voter: user) + + expect(latina_investment.can_vote_in_another_heading?(user)).to eq(false) + end + end end end