Merge pull request #1388 from consul/recounting

Creation of Partial Results for Poll Officers
This commit is contained in:
Raimond Garcia
2017-02-02 16:39:24 +01:00
committed by GitHub
21 changed files with 579 additions and 14 deletions

View File

@@ -0,0 +1,112 @@
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
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
def index
@booth_assignment = ::Poll::BoothAssignment.includes(:booth).find(index_params[:booth_assignment_id])
if current_user.poll_officer.officer_assignments.final.
where(booth_assignment_id: @booth_assignment.id).exists?
@partial_results = ::Poll::PartialResult.includes(:question).
where(booth_assignment_id: index_params[:booth_assignment_id]).
where(date: index_params[:date])
end
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
load_partial_results
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 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 results_params
params.permit(:officer_assignment_id, :date, :questions)
end
def index_params
params.permit(:booth_assignment_id, :date)
end
end

View File

@@ -13,7 +13,7 @@ module OfficingHelper
officer_assignments.each do |oa|
options << ["#{oa.booth_assignment.booth.name}", oa.id]
end
options_for_select(options)
options_for_select(options, params[:oa])
end
def recount_to_compare_with_final_recount(final_recount)
@@ -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

View File

@@ -25,7 +25,7 @@ module PollsHelper
(poll.starts_at.to_date..poll.ends_at.to_date).each do |date|
options << [l(date, format: :long), l(date)]
end
options_for_select(options)
options_for_select(options, params[:d])
end
def poll_final_recount_option(poll)

View File

@@ -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

View File

@@ -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

View File

@@ -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
@@ -13,4 +15,14 @@ class Poll::PartialResult < ActiveRecord::Base
scope :by_author, -> (author_id) { where(author_id: author_id) }
scope :by_question, -> (question_id) { where(question_id: question_id) }
before_save :update_logs
def update_logs
if self.amount_changed? && self.amount_was.present?
self.amount_log += ":#{self.amount_was.to_s}"
self.officer_assignment_id_log += ":#{self.officer_assignment_id_was.to_s}"
self.author_id_log += ":#{self.author_id_was.to_s}"
end
end
end

View File

@@ -15,7 +15,7 @@
<% end %>
</li>
<li <%= "class=active" if ["final_recounts"].include?(controller_name) || (controller_name == "polls" && action_name == "final") %>>
<li <%= "class=active" if ["final_recounts", "results"].include?(controller_name) || (controller_name == "polls" && action_name == "final") %>>
<%= link_to final_officing_polls_path do %>
<span class="icon-user"></span>
<%= t("officing.menu.final_recounts") %>

View File

@@ -53,6 +53,7 @@
<th><%= t("officing.final_recounts.new.booth") %></th>
<th><%= t("officing.final_recounts.new.count") %></th>
<th><%= t("officing.final_recounts.new.system_count") %></th>
<th>&nbsp;</th>
</thead>
<tbody>
<% @final_recounts.each do |final_recount| %>
@@ -69,6 +70,9 @@
<td>
<strong><%= system_recount_to_compare_with_final_recount final_recount %></strong>
</td>
<td>
<%= link_to t("officing.final_recounts.new.add_results"), new_officing_poll_result_path(@poll, oa: final_recount.officer_assignment.id, d: l(final_recount.date.to_date) )%>
</td>
</tr>
<% end %>
</tbody>

View File

@@ -3,21 +3,23 @@
<% if @polls.any? %>
<table>
<thead>
<th><%= t("officing.polls.final.select_poll") %></th>
<th>&nbsp;</th>
<th colspan="2"><%= t("officing.polls.final.select_poll") %></th>
</thead>
<tbody>
<% @polls.each do |poll| %>
<tr id="<%= dom_id(poll) %>" class="poll">
<td>
<strong>
<%= link_to poll.name, new_officing_poll_final_recount_path(poll) %>
<%= poll.name %>
</strong>
</td>
<td class="text-right">
<%= link_to t("officing.polls.final.add_recount"),
new_officing_poll_final_recount_path(poll),
class: "button hollow" %>
<%= link_to t("officing.polls.final.add_results"),
new_officing_poll_result_path(poll),
class: "button hollow" %>
</td>
</tr>
<% end %>

View File

@@ -0,0 +1,30 @@
<%= back_link_to new_officing_poll_result_path(@poll) %>
<h2><%= @poll.name %> - <%= t("officing.results.index.results") %></h2>
<% if @partial_results.present? %>
<div class="callout primary">
<h3><%= @booth_assignment.booth.name %> - <%= l @partial_results.first.date, format: :long %></h3>
</div>
<% by_question = @partial_results.group_by(&:question_id) %>
<% @poll.questions.each do |question| %>
<h3><%= question.title %></h3>
<table>
<tbody>
<% question.valid_answers.each_with_index do |answer, i| %>
<% by_answer = by_question[question.id].present? ? by_question[question.id].group_by(&:answer) : {} %>
<tr id="question_<%= question.id %>_<%= i %>_result">
<td><%= answer %></td>
<td><%= by_answer[answer].present? ? by_answer[answer].first.amount : 0 %></td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
<% else %>
<div class="callout primary">
<%= t("officing.results.index.no_results") %>
</div>
<% end %>

View File

@@ -0,0 +1,99 @@
<% if @officer_assignments.any? %>
<h2><%= t("officing.results.new.title", poll: @poll.name) %></h2>
<%= form_tag(officing_poll_results_path(@poll), {id: "officer_assignment_form"}) do %>
<div class="row">
<div class="small-12 medium-6 column">
<label><%= t("officing.results.new.booth") %></label>
<%= select_tag :officer_assignment_id,
booths_for_officer_select_options(@officer_assignments),
{ prompt: t("officing.results.new.select_booth"),
label: false } %>
</div>
</div>
<div class="row">
<div class="small-12 medium-6 column">
<label><%= t("officing.results.new.date") %></label>
<%= select_tag :date,
poll_dates_select_options(@poll),
{ prompt: t("officing.results.new.select_date"),
label: false } %>
</div>
</div>
<% @poll.questions.each do |question| %>
<div class="row">
<div class="small-12 column">
<h3><%= question.title %></h3>
</div>
<% question.valid_answers.each_with_index do |answer, i| %>
<div class="small-12 medium-6 large-3 column end">
<label><%= answer %></label>
<%= text_field_tag "questions[#{question.id}][#{i}]", answer_result_value(question.id, i), placeholder: "0" %>
</div>
<% end %>
</div>
<hr>
<% end %>
<div class="row">
<div class="small-12 medium-6 large-3 column">
<h3><%= t("officing.results.new.ballots_blank") %></h3>
<%= text_field_tag :count, nil, placeholder: "0" %>
</div>
<div class="small-12 medium-6 large-3 column end">
<h3><%= t("officing.results.new.ballots_null") %></h3>
<%= text_field_tag :count, nil, placeholder: "0" %>
</div>
</div>
<hr>
<div class="row">
<div class="small-12 medium-6 large-3 column">
<%= submit_tag t("officing.results.new.submit"), class: "button expanded" %>
</div>
</div>
<% end %>
<% else %>
<h2><%= @poll.name %></h2>
<div class="callout alert">
<%= t("officing.results.new.not_allowed") %>
</div>
<% end %>
<% if @partial_results.present? %>
<hr>
<h3><%= t("officing.results.new.results_list") %></h3>
<table>
<thead>
<th><%= t("officing.results.new.date") %></th>
<th><%= t("officing.results.new.booth") %></th>
<th>&nbsp;</th>
</thead>
<tbody>
<% 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| %>
<tr id="results_<%= booth_assignment %>_<%= date.strftime('%Y%m%d') %>">
<td>
<%= l(date, format: :long) %>
</td>
<td>
<%= results_by_booth[booth_assignment].first.booth_assignment.booth.name %>
</td>
<td>
<%= link_to t("officing.results.new.see_results"), officing_poll_results_path(@poll, date: l(date), booth_assignment_id: booth_assignment) %>
</td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
<% end %>