diff --git a/app/controllers/officing/voters_controller.rb b/app/controllers/officing/voters_controller.rb index dee1e00bd..a5343f83d 100644 --- a/app/controllers/officing/voters_controller.rb +++ b/app/controllers/officing/voters_controller.rb @@ -12,7 +12,8 @@ class Officing::VotersController < Officing::BaseController @voter = Poll::Voter.new(document_type: @user.document_type, document_number: @user.document_number, user: @user, - poll: @poll) + poll: @poll, + origin: "booth") @voter.save! end diff --git a/app/models/poll.rb b/app/models/poll.rb index 24ffa3a06..78ef2bc90 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -61,6 +61,10 @@ class Poll < ActiveRecord::Base voters.where(document_number: document_number, document_type: document_type).exists? end + def voted_in_booth?(user) + Poll::Voter.where(poll: self, user: user, origin: "booth").exists? + end + def date_range unless starts_at.present? && ends_at.present? && starts_at <= ends_at errors.add(:starts_at, I18n.t('errors.messages.invalid_date_range')) diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb index c2ea5724b..01eebd553 100644 --- a/app/models/poll/answer.rb +++ b/app/models/poll/answer.rb @@ -15,6 +15,6 @@ class Poll::Answer < ActiveRecord::Base scope :by_question, ->(question_id) { where(question_id: question_id) } def record_voter_participation - Poll::Voter.find_or_create_by!(user: author, poll: poll) + Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web") end end \ No newline at end of file diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb index 02ab70525..6895397de 100644 --- a/app/views/polls/show.html.erb +++ b/app/views/polls/show.html.erb @@ -31,8 +31,14 @@
- <% @questions.each do |question| %> - <%= render 'polls/questions/question', question: question %> + <% if @poll.voted_in_booth?(current_user) %> +
+ <%= t("polls.show.already_voted_in_booth") %> +
+ <% else %> + <% @questions.each do |question| %> + <%= render 'polls/questions/question', question: question %> + <% end %> <% end %>
diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index 29c81c074..67d8eef2c 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -481,6 +481,7 @@ en: help_text_1: "Voting takes place when a citizen proposal supports reaches 1% of the census with voting rights. Voting can also include questions that the City Council ask to the citizens decision." help_text_2: "To participate in the next vote you have to sign up on %{org} and verify your account. All registered voters in the city over 16 years old can vote. The results of all votes are binding on the government." show: + already_voted_in_booth: "You have already participated in a booth for this poll." dates_title: "Participation dates" cant_answer_not_logged_in: "You must %{signin} or %{signup} to participate." signin: Sign in diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index c5322c84c..cace38212 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -481,6 +481,7 @@ es: help_text_1: "Las votaciones se convocan cuando una propuesta ciudadana alcanza el 1% de apoyos del censo con derecho a voto. En las votaciones también se pueden incluir cuestiones que el Ayuntamiento somete a decisión directa de la ciudadanía." help_text_2: "Para participar en la próxima votación tienes que registrarte en %{org} y verificar tu cuenta. Pueden votar todas las personas empadronadas en la ciudad mayores de 16 años. Los resultados de todas las votaciones serán vinculantes para el gobierno." show: + already_voted_in_booth: "Ya has participado en esta votación en una urna." dates_title: "Fechas de participación" cant_answer_not_logged_in: "Necesitas %{signin} o %{signup} para participar." signin: iniciar sesión diff --git a/spec/factories.rb b/spec/factories.rb index f3d70a529..a67cd2e8e 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -52,6 +52,12 @@ FactoryGirl.define do trait :verified do verified_at Time.current end + + trait :in_census do + document_number "12345678Z" + document_type "1" + verified_at Time.current + end end factory :identity do diff --git a/spec/features/polls/voter_spec.rb b/spec/features/polls/voter_spec.rb new file mode 100644 index 000000000..08bc6f963 --- /dev/null +++ b/spec/features/polls/voter_spec.rb @@ -0,0 +1,94 @@ +require 'rails_helper' + +feature "Voter" do + + context "Origin" do + + scenario "Voting via web", :js do + poll = create(:poll) + question = create(:poll_question, poll: poll, valid_answers: 'Yes, No') + user = create(:user, :level_two) + + login_as user + visit question_path(question) + + click_link 'Answer this question' + click_link 'Yes' + + expect(page).to_not have_link('Yes') + expect(Poll::Voter.count).to eq(1) + expect(Poll::Voter.first.origin).to eq("web") + end + + scenario "Voting in booth", :js do + user = create(:user, :in_census) + create(:geozone, :in_census) + + poll = create(:poll) + officer = create(:poll_officer) + + ba = create(:poll_booth_assignment, poll: poll) + create(:poll_officer_assignment, officer: officer, booth_assignment: ba) + + login_through_form_as_officer(officer.user) + + visit new_officing_residence_path + officing_verify_residence + + expect(page).to have_content poll.name + + first(:button, "Confirm vote").click + expect(page).to have_content "Vote introduced!" + + expect(Poll::Voter.count).to eq(1) + expect(Poll::Voter.first.origin).to eq("booth") + end + + context "Trying to vote the same poll in booth and web" do + + let(:poll) { create(:poll) } + let(:question) { create(:poll_question, poll: poll, valid_answers: 'Yes, No') } + let!(:user) { create(:user, :in_census) } + + let(:officer) { create(:poll_officer) } + let(:ba) { create(:poll_booth_assignment, poll: poll) } + let!(:oa) { create(:poll_officer_assignment, officer: officer, booth_assignment: ba) } + + scenario "Trying to vote in web and then in booth", :js do + login_as user + vote_for_poll_via_web + + click_link "Sign out" + + login_through_form_as_officer(officer.user) + + visit new_officing_residence_path + officing_verify_residence + + expect(page).to have_content poll.name + expect(page).to_not have_button "Confirm vote" + expect(page).to have_content "Has already participated in this poll" + end + + scenario "Trying to vote in booth and then in web", :js do + login_through_form_as_officer(officer.user) + + vote_for_poll_via_booth + + visit root_path + click_link "Sign out" + + login_as user + visit question_path(question) + + click_link 'Answer this question' + + expect(page).to_not have_link('Yes') + expect(page).to have_content "You have already participated in a booth for this poll." + expect(Poll::Voter.count).to eq(1) + end + end + + end + +end \ No newline at end of file diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb index ac0cc44ea..5083d7439 100644 --- a/spec/models/poll/poll_spec.rb +++ b/spec/models/poll/poll_spec.rb @@ -138,4 +138,33 @@ describe :poll do end end end + + describe "#voted_in_booth?" do + + it "returns true if the user has already voted in booth" do + user = create(:user, :level_two) + poll = create(:poll) + + create(:poll_voter, poll: poll, user: user, origin: "booth") + + expect(poll.voted_in_booth?(user)).to be + end + + it "returns false if the user has not already voted in a booth" do + user = create(:user, :level_two) + poll = create(:poll) + + expect(poll.voted_in_booth?(user)).to_not be + end + + it "returns false if the user has voted in web" do + user = create(:user, :level_two) + poll = create(:poll) + + create(:poll_voter, poll: poll, user: user, origin: "web") + + expect(poll.voted_in_booth?(user)).to_not be + end + + end end diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb index 8b8470293..97f05294c 100644 --- a/spec/support/common_actions.rb +++ b/spec/support/common_actions.rb @@ -24,6 +24,17 @@ module CommonActions click_button 'Enter' end + def login_through_form_as_officer(user) + visit root_path + click_link 'Sign in' + + fill_in 'user_login', with: user.email + fill_in 'user_password', with: user.password + + click_button 'Enter' + visit new_officing_residence_path + end + def login_as_authenticated_manager expected_response = {login: login, user_key: user_key, date: date}.with_indifferent_access login, user_key, date = "JJB042", "31415926", Time.current.strftime("%Y%m%d%H%M%S") @@ -287,4 +298,26 @@ module CommonActions end end + def vote_for_poll_via_web + visit question_path(question) + + click_link 'Answer this question' + click_link 'Yes' + + expect(page).to_not have_link('Yes') + expect(Poll::Voter.count).to eq(1) + end + + def vote_for_poll_via_booth + visit new_officing_residence_path + officing_verify_residence + + expect(page).to have_content poll.name + + first(:button, "Confirm vote").click + expect(page).to have_content "Vote introduced!" + + expect(Poll::Voter.count).to eq(1) + end + end