From 592fdffe4e31f5898f7730d568730ea9fa2959a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 2 Feb 2017 14:44:44 +0100 Subject: [PATCH] adds results creation by poll officers --- .../officing/results_controller.rb | 101 ++++++++++++++---- app/helpers/officing_helper.rb | 7 ++ app/models/poll/booth_assignment.rb | 1 + app/models/poll/officer_assignment.rb | 1 + app/models/poll/partial_result.rb | 4 +- app/views/officing/results/new.html.erb | 37 ++++++- config/locales/officing.en.yml | 5 +- config/locales/officing.es.yml | 3 + spec/features/officing/final_recount_spec.rb | 4 +- spec/features/officing/results_spec.rb | 75 +++++++++++++ 10 files changed, 209 insertions(+), 29 deletions(-) create mode 100644 spec/features/officing/results_spec.rb diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb index be6f312bf..cffd3e0d0 100644 --- a/app/controllers/officing/results_controller.rb +++ b/app/controllers/officing/results_controller.rb @@ -1,41 +1,96 @@ class Officing::ResultsController < Officing::BaseController before_action :load_poll + + before_action :load_officer_assignments, only: :new + before_action :load_partial_results, only: :new + before_action :load_officer_assignment, only: :create + before_action :check_booth_and_date, only: :create + before_action :build_results, only: :create def new - @officer_assignments = ::Poll::OfficerAssignment. + end + + def create + @results.each { |result| result.save! } + + notice = t("officing.results.flash.create") + redirect_to new_officing_poll_result_path(@poll), notice: notice + end + + private + + def check_booth_and_date + if @officer_assignment.blank? + go_back_to_new(t("officing.results.flash.error_wrong_booth")) + elsif results_params[:date].blank? || + Date.parse(results_params[:date]) < @poll.starts_at.to_date || + Date.parse(results_params[:date]) > @poll.ends_at.to_date + go_back_to_new(t("officing.results.flash.error_wrong_date")) + end + end + + def build_results + @results = [] + + params[:questions].each_pair do |question_id, results| + question = @poll.questions.find(question_id) + go_back_to_new if question.blank? + + results.each_pair do |answer_index, count| + if count.present? + answer = question.valid_answers[answer_index.to_i] + go_back_to_new if question.blank? + + partial_result = ::Poll::PartialResult.find_or_initialize_by(booth_assignment_id: @officer_assignment.booth_assignment_id, + date: results_params[:date], + question_id: question_id, + answer: answer) + partial_result.officer_assignment_id = @officer_assignment.id + partial_result.amount = count.to_i + partial_result.author = current_user + partial_result.origin = 'booth' + @results << partial_result + end + end + end + end + + def go_back_to_new(alert = nil) + params[:d] = results_params[:date] + params[:oa] = results_params[:officer_assignment_id] + flash.now[:alert] = (alert || t("officing.results.flash.error_create")) + load_officer_assignments + render :new + end + + def load_poll + @poll = ::Poll.expired.includes(:questions).find(params[:poll_id]) + end + + def load_officer_assignment + @officer_assignment = current_user.poll_officer. + officer_assignments.final.find_by(id: results_params[:officer_assignment_id]) + end + + def load_officer_assignments + @officer_assignments = ::Poll::OfficerAssignment. includes(booth_assignment: [:booth]). joins(:booth_assignment). final. where(id: current_user.poll_officer.officer_assignment_ids). where("poll_booth_assignments.poll_id = ?", @poll.id). order(date: :asc) - end - - def create - if false - notice = t("officing.results.flash.create") - else - notice = t("officing.results.flash.error_create") - end - redirect_to new_officing_poll_result_path(@poll), notice: notice - end - - private - def load_poll - @poll = Poll.expired.includes(:questions).find(params[:poll_id]) end - def load_officer_assignment - @officer_assignment = current_user.poll_officer. - officer_assignments.final.find_by(id: final_recount_params[:officer_assignment_id]) - if @officer_assignment.blank? - redirect_to new_officing_poll_result_path(@poll), notice: t("officing.results.flash.error_create") + def load_partial_results + if @officer_assignments.present? + @partial_results = ::Poll::PartialResult.where(officer_assignment_id: @officer_assignments.map(&:id)).order(:booth_assignment_id, :date) end end - def final_recount_params - params.permit(:officer_assignment_id, :count, :date) + def results_params + params.permit(:officer_assignment_id, :date, :questions) end -end \ No newline at end of file +end diff --git a/app/helpers/officing_helper.rb b/app/helpers/officing_helper.rb index 43916fc24..eb7513e87 100644 --- a/app/helpers/officing_helper.rb +++ b/app/helpers/officing_helper.rb @@ -25,4 +25,11 @@ module OfficingHelper final_recount.booth_assignment.voters.select {|v| v.created_at.to_date == final_recount.date}.size end + def answer_result_value(question_id, answer_index) + return nil if params.blank? + return nil if params[:questions].blank? + return nil if params[:questions][question_id.to_s].blank? + params[:questions][question_id.to_s][answer_index.to_s] + end + end \ No newline at end of file diff --git a/app/models/poll/booth_assignment.rb b/app/models/poll/booth_assignment.rb index 057a58d27..bb507d0b8 100644 --- a/app/models/poll/booth_assignment.rb +++ b/app/models/poll/booth_assignment.rb @@ -8,5 +8,6 @@ class Poll has_many :final_recounts, class_name: "Poll::FinalRecount", dependent: :destroy has_many :officers, through: :officer_assignments has_many :voters + has_many :partial_results end end diff --git a/app/models/poll/officer_assignment.rb b/app/models/poll/officer_assignment.rb index 736deb54b..ed1902ab8 100644 --- a/app/models/poll/officer_assignment.rb +++ b/app/models/poll/officer_assignment.rb @@ -4,6 +4,7 @@ class Poll belongs_to :booth_assignment has_one :recount has_many :final_recounts + has_many :partial_results has_many :voters validates :officer_id, presence: true diff --git a/app/models/poll/partial_result.rb b/app/models/poll/partial_result.rb index 3dc432f1c..037395277 100644 --- a/app/models/poll/partial_result.rb +++ b/app/models/poll/partial_result.rb @@ -1,9 +1,11 @@ class Poll::PartialResult < ActiveRecord::Base - VALID_ORIGINS = %w{ web } + VALID_ORIGINS = %w{ web booth } belongs_to :question, -> { with_hidden } belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' + belongs_to :booth_assignment + belongs_to :officer_assignment validates :question, presence: true validates :author, presence: true diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index 7d55537f6..146a99699 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -27,10 +27,10 @@

<%= question.title %>

- <% question.valid_answers.each do |answer| %> + <% question.valid_answers.each_with_index do |answer, i| %>
- <%= text_field_tag :count, nil, placeholder: "0" %> + <%= text_field_tag "questions[#{question.id}][#{i}]", answer_result_value(question.id, i), placeholder: "0" %>
<% end %> @@ -64,3 +64,36 @@ <% end %> +<% if @partial_results.present? %> + +
+

<%= t("officing.results.new.results_list") %>

+ + + + + + + + + <% results_by_booth = @partial_results.group_by(&:booth_assignment_id) %> + <% results_by_booth.keys.each do |booth_assignment| %> + <% results_by_booth[booth_assignment].group_by(&:date).keys.each do |date| %> + + + + + + <% end %> + <% end %> + +
<%= t("officing.results.new.date") %><%= t("officing.results.new.booth") %> 
+ <%= l(date.to_date, format: :long) %> + + <%= results_by_booth[booth_assignment].first.booth_assignment.booth.name %> + + +
+ +<% end %> + diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index fd1987833..048002e7f 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -8,7 +8,7 @@ en: menu: voters: Validate document recounts: Store recount - final_recounts: Final recounts + final_recounts: Final recounts and results polls: index: title: Poll list @@ -57,6 +57,8 @@ en: flash: create: "Results saved" error_create: "Results NOT saved. Error in data." + error_wrong_booth: "Wrong booth. Results NOT saved." + error_wrong_date: "Wrong date. Results NOT saved." new: title: "%{poll} - Add results" not_allowed: "You are allowed to add results for this poll" @@ -67,6 +69,7 @@ en: ballots_blank: "Blank ballots" ballots_null: "Invalid ballots" submit: "Save" + results_list: "Your results" residence: flash: create: "Document verified with Census" diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index 79e8b4f98..645876309 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -57,6 +57,8 @@ es: flash: create: "Datos guardados" error_create: "Resultados NO añadidos. Error en los datos" + error_wrong_booth: "Urna incorrecta. Resultados NO guardados." + error_wrong_date: "Fecha incorrecta. Resultados NO guardados." new: title: "%{poll} - Añadir resultados" not_allowed: "No tienes permiso para introducir resultados" @@ -67,6 +69,7 @@ es: ballots_blank: "Papeletas en blanco" ballots_null: "Papeletas nulas" submit: "Guardar" + results_list: "Tus resultados" residence: flash: create: "Documento verificado con el Padrón" diff --git a/spec/features/officing/final_recount_spec.rb b/spec/features/officing/final_recount_spec.rb index 75ecbf7ec..1fcfa48a1 100644 --- a/spec/features/officing/final_recount_spec.rb +++ b/spec/features/officing/final_recount_spec.rb @@ -24,7 +24,7 @@ feature 'Officing Final Recount' do expect(page).to have_content('Poll officing') within('#side_menu') do - click_link 'Final recounts' + click_link 'Final recounts and results' end expect(page).to_not have_content(not_allowed_poll_1.name) @@ -40,7 +40,7 @@ feature 'Officing Final Recount' do visit officing_root_path within('#side_menu') do - click_link 'Final recounts' + click_link 'Final recounts and results' end within("#poll_#{@poll.id}") do diff --git a/spec/features/officing/results_spec.rb b/spec/features/officing/results_spec.rb new file mode 100644 index 000000000..b4129645b --- /dev/null +++ b/spec/features/officing/results_spec.rb @@ -0,0 +1,75 @@ +require 'rails_helper' + +feature 'Officing Results' do + + background do + @poll_officer = create(:poll_officer) + @officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer) + @poll = @officer_assignment.booth_assignment.poll + @poll.update(ends_at: 1.day.ago) + @question_1 = create(:poll_question, poll: @poll, valid_answers: "Yes,No") + @question_2 = create(:poll_question, poll: @poll, valid_answers: "Today,Tomorrow") + login_as(@poll_officer.user) + end + + scenario 'Only polls where user is officer for results are accessible' do + regular_officer_assignment_1 = create(:poll_officer_assignment, officer: @poll_officer) + regular_officer_assignment_2 = create(:poll_officer_assignment, officer: @poll_officer) + + not_allowed_poll_1 = create(:poll, :expired) + not_allowed_poll_2 = regular_officer_assignment_1.booth_assignment.poll + not_allowed_poll_2.update(ends_at: 1.day.ago) + not_allowed_poll_3 = regular_officer_assignment_2.booth_assignment.poll + + visit root_path + click_link 'Polling officers' + + expect(page).to have_content('Poll officing') + within('#side_menu') do + click_link 'Final recounts and results' + end + + expect(page).to_not have_content(not_allowed_poll_1.name) + expect(page).to_not have_content(not_allowed_poll_2.name) + expect(page).to_not have_content(not_allowed_poll_3.name) + expect(page).to have_content(@poll.name) + + visit new_officing_poll_result_path(not_allowed_poll_1) + expect(page).to have_content('You are allowed to add results for this poll') + end + + scenario 'Add results' do + visit officing_root_path + + within('#side_menu') do + click_link 'Final recounts and results' + end + + within("#poll_#{@poll.id}") do + expect(page).to have_content(@poll.name) + click_link 'Add results' + end + + expect(page).to_not have_content('Your results') + + booth_name = @officer_assignment.booth_assignment.booth.name + date = I18n.l(@poll.starts_at.to_date, format: :long) + select booth_name, from: 'officer_assignment_id' + select date, from: 'date' + + fill_in "questions[#{@question_1.id}][0]", with: '100' + fill_in "questions[#{@question_1.id}][1]", with: '200' + + fill_in "questions[#{@question_2.id}][0]", with: '333' + fill_in "questions[#{@question_2.id}][1]", with: '444' + click_button 'Save' + + expect(page).to have_content('Your results') + + within("#results_#{@officer_assignment.booth_assignment_id}_#{@poll.starts_at.to_date.strftime('%Y%m%d')}") do + expect(page).to have_content(date) + expect(page).to have_content(booth_name) + end + end + +end \ No newline at end of file