From 0540430bfddf70c30db08937c50e4643c6e43912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 12:37:47 +0100 Subject: [PATCH 01/25] adds date and booth/officer trace fields to poll partial results --- ...20170201113206_adds_fields_to_poll_partial_results.rb | 9 +++++++++ db/schema.rb | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb diff --git a/db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb b/db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb new file mode 100644 index 000000000..3755dc700 --- /dev/null +++ b/db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb @@ -0,0 +1,9 @@ +class AddsFieldsToPollPartialResults < ActiveRecord::Migration + def change + add_column :poll_partial_results, :date, :date + add_column :poll_partial_results, :booth_assignment_id, :integer + add_column :poll_partial_results, :officer_assignment_id, :integer + + add_index :poll_partial_results, [:booth_assignment_id, :date] + end +end diff --git a/db/schema.rb b/db/schema.rb index 544d2a6ff..13ad1dce7 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: 20170130171322) do +ActiveRecord::Schema.define(version: 20170201113206) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -430,10 +430,14 @@ ActiveRecord::Schema.define(version: 20170130171322) do t.string "answer" t.integer "amount" t.string "origin" + t.date "date" + t.integer "booth_assignment_id" + t.integer "officer_assignment_id" end add_index "poll_partial_results", ["answer"], name: "index_poll_partial_results_on_answer", using: :btree add_index "poll_partial_results", ["author_id"], name: "index_poll_partial_results_on_author_id", using: :btree + add_index "poll_partial_results", ["booth_assignment_id", "date"], name: "index_poll_partial_results_on_booth_assignment_id_and_date", using: :btree add_index "poll_partial_results", ["origin"], name: "index_poll_partial_results_on_origin", using: :btree add_index "poll_partial_results", ["question_id"], name: "index_poll_partial_results_on_question_id", using: :btree From 5531b5e4697d7e34a6d9c76a46ca48f644aec655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 12:47:58 +0100 Subject: [PATCH 02/25] adds selected option via params for helper methods --- app/helpers/officing_helper.rb | 2 +- app/helpers/polls_helper.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/helpers/officing_helper.rb b/app/helpers/officing_helper.rb index 842eaee63..43916fc24 100644 --- a/app/helpers/officing_helper.rb +++ b/app/helpers/officing_helper.rb @@ -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) diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb index 214234762..5425a6b52 100644 --- a/app/helpers/polls_helper.rb +++ b/app/helpers/polls_helper.rb @@ -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) From a9a93ed441c7d4d3dc571271446727d28fe08f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:25:39 +0100 Subject: [PATCH 03/25] adds basic new view for officing results --- .../officing/results_controller.rb | 41 ++++++++++++ app/views/officing/results/new.html.erb | 65 +++++++++++++++++++ config/locales/officing.en.yml | 15 +++++ config/locales/officing.es.yml | 15 +++++ config/routes.rb | 1 + 5 files changed, 137 insertions(+) create mode 100644 app/controllers/officing/results_controller.rb create mode 100644 app/views/officing/results/new.html.erb diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb new file mode 100644 index 000000000..be6f312bf --- /dev/null +++ b/app/controllers/officing/results_controller.rb @@ -0,0 +1,41 @@ +class Officing::ResultsController < Officing::BaseController + before_action :load_poll + before_action :load_officer_assignment, only: :create + + def new + @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") + end + end + + def final_recount_params + params.permit(:officer_assignment_id, :count, :date) + end + +end \ No newline at end of file diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb new file mode 100644 index 000000000..0e57f640d --- /dev/null +++ b/app/views/officing/results/new.html.erb @@ -0,0 +1,65 @@ +<% if @officer_assignments.any? %> +

<%= t("officing.results.new.title", poll: @poll.name) %>

+ + <%= form_tag(officing_poll_results_path(@poll), {id: "officer_assignment_form"}) do %> +
+
+ + <%= select_tag :officer_assignment_id, + booths_for_officer_select_options(@officer_assignments), + { prompt: t("officing.results.new.select_booth"), + label: false } %> +
+
+ +
+
+ + <%= select_tag :date, + poll_dates_select_options(@poll), + { prompt: t("officing.results.new.select_date"), + label: false } %> +
+
+ + <% @poll.questions.each do |question| %> +
+

<%= question.title %>

+ <% question.valid_answers.each do |answer| %> +
+ + <%= text_field_tag :count, nil, placeholder: "0" %> +
+ <% end %> +
+
+ <% end %> + +
+

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

+
+ <%= text_field_tag :count, nil, placeholder: "0" %> +
+
+
+

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

+
+ <%= text_field_tag :count, nil, placeholder: "0" %> +
+
+ + +
+
+ <%= submit_tag t("officing.results.new.submit"), class: "button expanded" %> +
+
+ <% end %> + +<% else %> +

<%= @poll.name %>

+
+ <%= t("officing.results.new.not_allowed") %> +
+<% end %> + diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index c591f7b03..084ceb4ba 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -20,6 +20,7 @@ en: no_polls: You are not officing final recounts in any active poll select_poll: Select poll add_recount: Add final recount + add_results: Add results recounts: flash: create: "Data added" @@ -51,6 +52,20 @@ en: submit: Save final_recount_list: "Your final recounts" system_count: "System recount" + results: + flash: + create: "Results saved" + error_create: "Results NOT saved. Error in data." + new: + title: "%{poll} - Add results" + not_allowed: "You are allowed to add results for this poll" + booth: "Booth" + date: "Date" + select_booth: "Select booth" + select_date: "Select date" + ballots_blank: "Blank ballots" + ballots_null: "Invalid ballots" + submit: "Save" residence: flash: create: "Document verified with Census" diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index 9de110454..56d6f745f 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -20,6 +20,7 @@ es: no_polls: "No tienes permiso para recuento final en ninguna votación reciente" select_poll: "Selecciona votación" add_recount: "Añadir recuentos finales" + add_results: "Añadir resultados" recounts: flash: create: "Datos añadidos" @@ -51,6 +52,20 @@ es: submit: "Guardar" final_recount_list: "Tus recuentos finales" system_count: "Recuento del sistema" + results: + flash: + create: "Datos guardados" + error_create: "Resultados NO añadidos. Error en los datos" + new: + title: "%{poll} - Añadir resultados" + not_allowed: "No tienes permiso para introducir resultados" + booth: "Urna" + date: "Día" + select_booth: "Elige urna" + select_date: "Elige día" + ballots_blank: "Papeletas en blanco" + ballots_null: "Papeletas nulas" + submit: "Guardar" residence: flash: create: "Documento verificado con el Padrón" diff --git a/config/routes.rb b/config/routes.rb index 8be55feb5..2295453b6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -336,6 +336,7 @@ Rails.application.routes.draw do resources :recounts, only: [:new, :create] resources :final_recounts, only: [:new, :create] + resources :results, only: [:new, :create] end resource :residence, controller: "residence", only: [:new, :create] resources :voters, only: [:new, :create] From 64c07a5d56ca519e7e6627b16e7a0bfce732e04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:26:02 +0100 Subject: [PATCH 04/25] adds link to add results for officers --- app/views/officing/polls/final.html.erb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/views/officing/polls/final.html.erb b/app/views/officing/polls/final.html.erb index 7159a3769..6bdeed269 100644 --- a/app/views/officing/polls/final.html.erb +++ b/app/views/officing/polls/final.html.erb @@ -5,13 +5,14 @@ <%= t("officing.polls.final.select_poll") %>   +   <% @polls.each do |poll| %> - <%= link_to poll.name, new_officing_poll_final_recount_path(poll) %> + <%= poll.name %> @@ -19,6 +20,11 @@ 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" %> + <% end %> From f6b03460ea74eeb21860951fbdad95eceec87fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:26:33 +0100 Subject: [PATCH 05/25] changes poll questions in dev_seeds to have different answers --- db/dev_seeds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index d9b09f70a..09278aa56 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -521,7 +521,7 @@ print "Creating Poll Questions" question = Poll::Question.create!(author: author, title: Faker::Lorem.sentence(3).truncate(60), description: description, - valid_answers: Faker::Lorem.words(3).join(', '), + valid_answers: Faker::Lorem.words((2..7).to_a.sample).join(', '), poll: poll) end From 2eaab52b12e052648501a848449a04fc16d26a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:58:50 +0100 Subject: [PATCH 06/25] fixes spec --- spec/features/officing/final_recount_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/features/officing/final_recount_spec.rb b/spec/features/officing/final_recount_spec.rb index e712f13f7..c9ed2a5c5 100644 --- a/spec/features/officing/final_recount_spec.rb +++ b/spec/features/officing/final_recount_spec.rb @@ -43,7 +43,10 @@ feature 'Officing Final Recount' do click_link 'Final recounts' end - click_link @poll.name + within("#poll_#{@poll.id}") do + expect(page).to have_content(@poll.name) + click_link 'Add final recount' + end expect(page).to_not have_content('Your recounts') From 5fbc9fb9a6da94191294e3ef240cd58848541c05 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Wed, 1 Feb 2017 14:00:38 +0100 Subject: [PATCH 07/25] improves styles on officing results new form --- app/views/officing/results/new.html.erb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index 0e57f640d..ed9c702d2 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -24,9 +24,11 @@ <% @poll.questions.each do |question| %>
-

<%= question.title %>

+
+

<%= question.title %>

+
<% question.valid_answers.each do |answer| %> -
+
<%= text_field_tag :count, nil, placeholder: "0" %>
From ee993a6aa550e85f36b4397a9f42387b8ced5c44 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Wed, 1 Feb 2017 14:10:59 +0100 Subject: [PATCH 08/25] adds styles to ballots blank and ballots null inputs --- app/views/officing/results/new.html.erb | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index ed9c702d2..7d55537f6 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -38,21 +38,20 @@ <% end %>
-

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

-
+
+

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

+ <%= text_field_tag :count, nil, placeholder: "0" %> +
+ +
+

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

<%= text_field_tag :count, nil, placeholder: "0" %>
-
-

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

-
- <%= text_field_tag :count, nil, placeholder: "0" %> -
-
- +
-
+
<%= submit_tag t("officing.results.new.submit"), class: "button expanded" %>
From 6584b3c44592c0f4f8695e913a558e6c608e05ee Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Wed, 1 Feb 2017 14:15:49 +0100 Subject: [PATCH 09/25] fixes html table on officing polls final --- app/views/officing/polls/final.html.erb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/views/officing/polls/final.html.erb b/app/views/officing/polls/final.html.erb index 6bdeed269..b46ab0b13 100644 --- a/app/views/officing/polls/final.html.erb +++ b/app/views/officing/polls/final.html.erb @@ -3,9 +3,7 @@ <% if @polls.any? %> - - - + <% @polls.each do |poll| %> @@ -19,8 +17,6 @@ <%= link_to t("officing.polls.final.add_recount"), new_officing_poll_final_recount_path(poll), class: "button hollow" %> - - + <% @final_recounts.each do |final_recount| %> @@ -69,6 +70,9 @@ + <% end %> diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index 084ceb4ba..fd1987833 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -52,6 +52,7 @@ en: submit: Save final_recount_list: "Your final recounts" system_count: "System recount" + add_results: "Add results" results: flash: create: "Results saved" diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index 56d6f745f..79e8b4f98 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -52,6 +52,7 @@ es: submit: "Guardar" final_recount_list: "Tus recuentos finales" system_count: "Recuento del sistema" + add_results: "Añadir resultados" results: flash: create: "Datos guardados" diff --git a/spec/features/officing/final_recount_spec.rb b/spec/features/officing/final_recount_spec.rb index c9ed2a5c5..75ecbf7ec 100644 --- a/spec/features/officing/final_recount_spec.rb +++ b/spec/features/officing/final_recount_spec.rb @@ -122,6 +122,26 @@ feature 'Officing Final Recount' do expect(page).to have_content('100') expect(page).to have_content('33') end - end + + scenario "Show link to add results for same booth/date" do + final_officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer) + poll = final_officer_assignment.booth_assignment.poll + poll.update(ends_at: 1.day.ago) + final_recount = create(:poll_final_recount, + officer_assignment: final_officer_assignment, + booth_assignment: final_officer_assignment.booth_assignment, + date: 7.days.ago, + count: 100) + visit new_officing_poll_final_recount_path(poll) + within("#poll_final_recount_#{final_recount.id}") do + click_link "Add results" + end + + expected_path = new_officing_poll_result_path(poll, oa: final_recount.officer_assignment.id, d: I18n.l(final_recount.date.to_date)) + expect(page).to have_current_path(expected_path) + expect(page).to have_select('officer_assignment_id', selected: final_recount.booth_assignment.booth.name) + expect(page).to have_select('date', selected: I18n.l(final_recount.date.to_date, format: :long)) + end + end \ No newline at end of file From f2dcd654714d830d80dded6f86b7f66f1e5fb387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 12:37:47 +0100 Subject: [PATCH 11/25] adds date and booth/officer trace fields to poll partial results --- ...20170201113206_adds_fields_to_poll_partial_results.rb | 9 +++++++++ db/schema.rb | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb diff --git a/db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb b/db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb new file mode 100644 index 000000000..3755dc700 --- /dev/null +++ b/db/migrate/20170201113206_adds_fields_to_poll_partial_results.rb @@ -0,0 +1,9 @@ +class AddsFieldsToPollPartialResults < ActiveRecord::Migration + def change + add_column :poll_partial_results, :date, :date + add_column :poll_partial_results, :booth_assignment_id, :integer + add_column :poll_partial_results, :officer_assignment_id, :integer + + add_index :poll_partial_results, [:booth_assignment_id, :date] + end +end diff --git a/db/schema.rb b/db/schema.rb index 544d2a6ff..13ad1dce7 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: 20170130171322) do +ActiveRecord::Schema.define(version: 20170201113206) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -430,10 +430,14 @@ ActiveRecord::Schema.define(version: 20170130171322) do t.string "answer" t.integer "amount" t.string "origin" + t.date "date" + t.integer "booth_assignment_id" + t.integer "officer_assignment_id" end add_index "poll_partial_results", ["answer"], name: "index_poll_partial_results_on_answer", using: :btree add_index "poll_partial_results", ["author_id"], name: "index_poll_partial_results_on_author_id", using: :btree + add_index "poll_partial_results", ["booth_assignment_id", "date"], name: "index_poll_partial_results_on_booth_assignment_id_and_date", using: :btree add_index "poll_partial_results", ["origin"], name: "index_poll_partial_results_on_origin", using: :btree add_index "poll_partial_results", ["question_id"], name: "index_poll_partial_results_on_question_id", using: :btree From 945020894da5ac8bb70c08b365247ce6f6eebb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 12:47:58 +0100 Subject: [PATCH 12/25] adds selected option via params for helper methods --- app/helpers/officing_helper.rb | 2 +- app/helpers/polls_helper.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/helpers/officing_helper.rb b/app/helpers/officing_helper.rb index 842eaee63..43916fc24 100644 --- a/app/helpers/officing_helper.rb +++ b/app/helpers/officing_helper.rb @@ -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) diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb index 214234762..5425a6b52 100644 --- a/app/helpers/polls_helper.rb +++ b/app/helpers/polls_helper.rb @@ -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) From 594ad3df7b6c97e3342d9d53c1ce4888c33784ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:25:39 +0100 Subject: [PATCH 13/25] adds basic new view for officing results --- .../officing/results_controller.rb | 41 ++++++++++++ app/views/officing/results/new.html.erb | 65 +++++++++++++++++++ config/locales/officing.en.yml | 15 +++++ config/locales/officing.es.yml | 15 +++++ config/routes.rb | 1 + 5 files changed, 137 insertions(+) create mode 100644 app/controllers/officing/results_controller.rb create mode 100644 app/views/officing/results/new.html.erb diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb new file mode 100644 index 000000000..be6f312bf --- /dev/null +++ b/app/controllers/officing/results_controller.rb @@ -0,0 +1,41 @@ +class Officing::ResultsController < Officing::BaseController + before_action :load_poll + before_action :load_officer_assignment, only: :create + + def new + @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") + end + end + + def final_recount_params + params.permit(:officer_assignment_id, :count, :date) + end + +end \ No newline at end of file diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb new file mode 100644 index 000000000..0e57f640d --- /dev/null +++ b/app/views/officing/results/new.html.erb @@ -0,0 +1,65 @@ +<% if @officer_assignments.any? %> +

<%= t("officing.results.new.title", poll: @poll.name) %>

+ + <%= form_tag(officing_poll_results_path(@poll), {id: "officer_assignment_form"}) do %> +
+
+ + <%= select_tag :officer_assignment_id, + booths_for_officer_select_options(@officer_assignments), + { prompt: t("officing.results.new.select_booth"), + label: false } %> +
+
+ +
+
+ + <%= select_tag :date, + poll_dates_select_options(@poll), + { prompt: t("officing.results.new.select_date"), + label: false } %> +
+
+ + <% @poll.questions.each do |question| %> +
+

<%= question.title %>

+ <% question.valid_answers.each do |answer| %> +
+ + <%= text_field_tag :count, nil, placeholder: "0" %> +
+ <% end %> +
+
+ <% end %> + +
+

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

+
+ <%= text_field_tag :count, nil, placeholder: "0" %> +
+
+
+

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

+
+ <%= text_field_tag :count, nil, placeholder: "0" %> +
+
+ + +
+
+ <%= submit_tag t("officing.results.new.submit"), class: "button expanded" %> +
+
+ <% end %> + +<% else %> +

<%= @poll.name %>

+
+ <%= t("officing.results.new.not_allowed") %> +
+<% end %> + diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index c591f7b03..084ceb4ba 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -20,6 +20,7 @@ en: no_polls: You are not officing final recounts in any active poll select_poll: Select poll add_recount: Add final recount + add_results: Add results recounts: flash: create: "Data added" @@ -51,6 +52,20 @@ en: submit: Save final_recount_list: "Your final recounts" system_count: "System recount" + results: + flash: + create: "Results saved" + error_create: "Results NOT saved. Error in data." + new: + title: "%{poll} - Add results" + not_allowed: "You are allowed to add results for this poll" + booth: "Booth" + date: "Date" + select_booth: "Select booth" + select_date: "Select date" + ballots_blank: "Blank ballots" + ballots_null: "Invalid ballots" + submit: "Save" residence: flash: create: "Document verified with Census" diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index 9de110454..56d6f745f 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -20,6 +20,7 @@ es: no_polls: "No tienes permiso para recuento final en ninguna votación reciente" select_poll: "Selecciona votación" add_recount: "Añadir recuentos finales" + add_results: "Añadir resultados" recounts: flash: create: "Datos añadidos" @@ -51,6 +52,20 @@ es: submit: "Guardar" final_recount_list: "Tus recuentos finales" system_count: "Recuento del sistema" + results: + flash: + create: "Datos guardados" + error_create: "Resultados NO añadidos. Error en los datos" + new: + title: "%{poll} - Añadir resultados" + not_allowed: "No tienes permiso para introducir resultados" + booth: "Urna" + date: "Día" + select_booth: "Elige urna" + select_date: "Elige día" + ballots_blank: "Papeletas en blanco" + ballots_null: "Papeletas nulas" + submit: "Guardar" residence: flash: create: "Documento verificado con el Padrón" diff --git a/config/routes.rb b/config/routes.rb index 8be55feb5..2295453b6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -336,6 +336,7 @@ Rails.application.routes.draw do resources :recounts, only: [:new, :create] resources :final_recounts, only: [:new, :create] + resources :results, only: [:new, :create] end resource :residence, controller: "residence", only: [:new, :create] resources :voters, only: [:new, :create] From 1998167f1750de44d0b641b57787bb9db631df6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:26:02 +0100 Subject: [PATCH 14/25] adds link to add results for officers --- app/views/officing/polls/final.html.erb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/views/officing/polls/final.html.erb b/app/views/officing/polls/final.html.erb index 7159a3769..6bdeed269 100644 --- a/app/views/officing/polls/final.html.erb +++ b/app/views/officing/polls/final.html.erb @@ -5,13 +5,14 @@
+ <% @polls.each do |poll| %> + <% end %> From c4a1c47feb04d44ef410b31ddafeaadd7d25ef84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:26:33 +0100 Subject: [PATCH 15/25] changes poll questions in dev_seeds to have different answers --- db/dev_seeds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index d9b09f70a..09278aa56 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -521,7 +521,7 @@ print "Creating Poll Questions" question = Poll::Question.create!(author: author, title: Faker::Lorem.sentence(3).truncate(60), description: description, - valid_answers: Faker::Lorem.words(3).join(', '), + valid_answers: Faker::Lorem.words((2..7).to_a.sample).join(', '), poll: poll) end From 5f55c9a10fb9f5647479d40ebd5cb01ee7d59b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 13:58:50 +0100 Subject: [PATCH 16/25] fixes spec --- spec/features/officing/final_recount_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/features/officing/final_recount_spec.rb b/spec/features/officing/final_recount_spec.rb index e712f13f7..c9ed2a5c5 100644 --- a/spec/features/officing/final_recount_spec.rb +++ b/spec/features/officing/final_recount_spec.rb @@ -43,7 +43,10 @@ feature 'Officing Final Recount' do click_link 'Final recounts' end - click_link @poll.name + within("#poll_#{@poll.id}") do + expect(page).to have_content(@poll.name) + click_link 'Add final recount' + end expect(page).to_not have_content('Your recounts') From 5d6993f77718b74b3aae7fa995f916ba7acb5be1 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Wed, 1 Feb 2017 14:00:38 +0100 Subject: [PATCH 17/25] improves styles on officing results new form --- app/views/officing/results/new.html.erb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index 0e57f640d..ed9c702d2 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -24,9 +24,11 @@ <% @poll.questions.each do |question| %>
-

<%= question.title %>

+
+

<%= question.title %>

+
<% question.valid_answers.each do |answer| %> -
+
<%= text_field_tag :count, nil, placeholder: "0" %>
From 8a42a7fc8017d2ae894ed31c776eb0eaeffd0c4c Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Wed, 1 Feb 2017 14:10:59 +0100 Subject: [PATCH 18/25] adds styles to ballots blank and ballots null inputs --- app/views/officing/results/new.html.erb | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index ed9c702d2..7d55537f6 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -38,21 +38,20 @@ <% end %>
-

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

-
+
+

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

+ <%= text_field_tag :count, nil, placeholder: "0" %> +
+ +
+

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

<%= text_field_tag :count, nil, placeholder: "0" %>
-
-

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

-
- <%= text_field_tag :count, nil, placeholder: "0" %> -
-
- +
-
+
<%= submit_tag t("officing.results.new.submit"), class: "button expanded" %>
From 60adc228306eab2f500a4ad284d0b1eb68723fbe Mon Sep 17 00:00:00 2001 From: Alberto Garcia Cabeza Date: Wed, 1 Feb 2017 14:15:49 +0100 Subject: [PATCH 19/25] fixes html table on officing polls final --- app/views/officing/polls/final.html.erb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/views/officing/polls/final.html.erb b/app/views/officing/polls/final.html.erb index 6bdeed269..b46ab0b13 100644 --- a/app/views/officing/polls/final.html.erb +++ b/app/views/officing/polls/final.html.erb @@ -3,9 +3,7 @@ <% if @polls.any? %>
<%= t("officing.polls.final.select_poll") %>  <%= t("officing.polls.final.select_poll") %>
<%= link_to t("officing.polls.final.add_results"), new_officing_poll_result_path(poll), class: "button hollow" %> From 3ebe96241cdb5f98d4ffe6e14e4268aaa22a2411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 16:22:04 +0100 Subject: [PATCH 10/25] adds link to results for each final recount in officing --- .../officing/final_recounts/new.html.erb | 4 ++++ config/locales/officing.en.yml | 1 + config/locales/officing.es.yml | 1 + spec/features/officing/final_recount_spec.rb | 22 ++++++++++++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/views/officing/final_recounts/new.html.erb b/app/views/officing/final_recounts/new.html.erb index ee09a1d38..647bd31b4 100644 --- a/app/views/officing/final_recounts/new.html.erb +++ b/app/views/officing/final_recounts/new.html.erb @@ -53,6 +53,7 @@ <%= t("officing.final_recounts.new.booth") %> <%= t("officing.final_recounts.new.count") %> <%= t("officing.final_recounts.new.system_count") %> 
<%= system_recount_to_compare_with_final_recount final_recount %> + <%= 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) )%> +
<%= t("officing.polls.final.select_poll") %>   
- <%= link_to poll.name, new_officing_poll_final_recount_path(poll) %> + <%= poll.name %> @@ -19,6 +20,11 @@ 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" %> +
- - - + <% @polls.each do |poll| %> @@ -19,8 +17,6 @@ <%= link_to t("officing.polls.final.add_recount"), new_officing_poll_final_recount_path(poll), class: "button hollow" %> - - + <% @final_recounts.each do |final_recount| %> @@ -69,6 +70,9 @@ + <% end %> diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index 084ceb4ba..fd1987833 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -52,6 +52,7 @@ en: submit: Save final_recount_list: "Your final recounts" system_count: "System recount" + add_results: "Add results" results: flash: create: "Results saved" diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index 56d6f745f..79e8b4f98 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -52,6 +52,7 @@ es: submit: "Guardar" final_recount_list: "Tus recuentos finales" system_count: "Recuento del sistema" + add_results: "Añadir resultados" results: flash: create: "Datos guardados" diff --git a/spec/features/officing/final_recount_spec.rb b/spec/features/officing/final_recount_spec.rb index c9ed2a5c5..75ecbf7ec 100644 --- a/spec/features/officing/final_recount_spec.rb +++ b/spec/features/officing/final_recount_spec.rb @@ -122,6 +122,26 @@ feature 'Officing Final Recount' do expect(page).to have_content('100') expect(page).to have_content('33') end - end + + scenario "Show link to add results for same booth/date" do + final_officer_assignment = create(:poll_officer_assignment, :final, officer: @poll_officer) + poll = final_officer_assignment.booth_assignment.poll + poll.update(ends_at: 1.day.ago) + final_recount = create(:poll_final_recount, + officer_assignment: final_officer_assignment, + booth_assignment: final_officer_assignment.booth_assignment, + date: 7.days.ago, + count: 100) + visit new_officing_poll_final_recount_path(poll) + within("#poll_final_recount_#{final_recount.id}") do + click_link "Add results" + end + + expected_path = new_officing_poll_result_path(poll, oa: final_recount.officer_assignment.id, d: I18n.l(final_recount.date.to_date)) + expect(page).to have_current_path(expected_path) + expect(page).to have_select('officer_assignment_id', selected: final_recount.booth_assignment.booth.name) + expect(page).to have_select('date', selected: I18n.l(final_recount.date.to_date, format: :long)) + end + end \ No newline at end of file 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 21/25] 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") %>

+ +
<%= t("officing.polls.final.select_poll") %>  <%= t("officing.polls.final.select_poll") %>
<%= link_to t("officing.polls.final.add_results"), new_officing_poll_result_path(poll), class: "button hollow" %> From 1f985ef8f3c45c2e83c6638cf4736220214560ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Wed, 1 Feb 2017 16:22:04 +0100 Subject: [PATCH 20/25] adds link to results for each final recount in officing --- .../officing/final_recounts/new.html.erb | 4 ++++ config/locales/officing.en.yml | 1 + config/locales/officing.es.yml | 1 + spec/features/officing/final_recount_spec.rb | 22 ++++++++++++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/views/officing/final_recounts/new.html.erb b/app/views/officing/final_recounts/new.html.erb index ee09a1d38..647bd31b4 100644 --- a/app/views/officing/final_recounts/new.html.erb +++ b/app/views/officing/final_recounts/new.html.erb @@ -53,6 +53,7 @@ <%= t("officing.final_recounts.new.booth") %> <%= t("officing.final_recounts.new.count") %> <%= t("officing.final_recounts.new.system_count") %> 
<%= system_recount_to_compare_with_final_recount final_recount %> + <%= 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) )%> +
+ + + + + + + <% 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 From d9fa4bdc29f8ffa5d95dfc53a4d9e9d071b37136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 2 Feb 2017 14:51:09 +0100 Subject: [PATCH 22/25] adds results to officing menu --- app/views/officing/_menu.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/officing/_menu.html.erb b/app/views/officing/_menu.html.erb index d6773a426..b6b94a62b 100644 --- a/app/views/officing/_menu.html.erb +++ b/app/views/officing/_menu.html.erb @@ -15,7 +15,7 @@ <% end %> -
  • > +
  • > <%= link_to final_officing_polls_path do %> <%= t("officing.menu.final_recounts") %> From ec8d45f3cdea5e17162517f3598971c34473d02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 2 Feb 2017 16:10:40 +0100 Subject: [PATCH 23/25] adds index view for poll results in officing --- .../officing/results_controller.rb | 15 +++++ app/views/officing/results/index.html.erb | 30 +++++++++ app/views/officing/results/new.html.erb | 4 +- config/locales/officing.en.yml | 4 ++ config/locales/officing.es.yml | 4 ++ config/routes.rb | 2 +- spec/features/officing/results_spec.rb | 64 +++++++++++++++++++ 7 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 app/views/officing/results/index.html.erb diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb index cffd3e0d0..e716b8c8b 100644 --- a/app/controllers/officing/results_controller.rb +++ b/app/controllers/officing/results_controller.rb @@ -18,6 +18,17 @@ class Officing::ResultsController < Officing::BaseController 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 @@ -93,4 +104,8 @@ class Officing::ResultsController < Officing::BaseController params.permit(:officer_assignment_id, :date, :questions) end + def index_params + params.permit(:booth_assignment_id, :date) + end + end diff --git a/app/views/officing/results/index.html.erb b/app/views/officing/results/index.html.erb new file mode 100644 index 000000000..a20a944ca --- /dev/null +++ b/app/views/officing/results/index.html.erb @@ -0,0 +1,30 @@ +<%= back_link_to new_officing_poll_result_path(@poll) %> +

    <%= @poll.name %> - <%= t("officing.results.index.results") %>

    + +<% if @partial_results.present? %> +
    +

    <%= @booth_assignment.booth.name %> - <%= l @partial_results.first.date, format: :long %>

    +
    + + <% by_question = @partial_results.group_by(&:question_id) %> + <% @poll.questions.each do |question| %> +

    <%= question.title %>

    + + + + <% question.valid_answers.each_with_index do |answer, i| %> + <% by_answer = by_question[question.id].present? ? by_question[question.id].group_by(&:answer) : {} %> + + + + + <% end %> + +
    <%= answer %><%= by_answer[answer].present? ? by_answer[answer].first.amount : 0 %>
    + + <% end %> +<% else %> +
    + <%= t("officing.results.index.no_results") %> +
    +<% end %> \ No newline at end of file diff --git a/app/views/officing/results/new.html.erb b/app/views/officing/results/new.html.erb index 146a99699..1d8dee7fd 100644 --- a/app/views/officing/results/new.html.erb +++ b/app/views/officing/results/new.html.erb @@ -81,13 +81,13 @@ <% results_by_booth[booth_assignment].group_by(&:date).keys.each do |date| %> - <%= l(date.to_date, format: :long) %> + <%= l(date, format: :long) %> <%= results_by_booth[booth_assignment].first.booth_assignment.booth.name %> - + <%= link_to t("officing.results.new.see_results"), officing_poll_results_path(@poll, date: l(date), booth_assignment_id: booth_assignment) %> <% end %> diff --git a/config/locales/officing.en.yml b/config/locales/officing.en.yml index 048002e7f..f5ce67400 100644 --- a/config/locales/officing.en.yml +++ b/config/locales/officing.en.yml @@ -70,6 +70,10 @@ en: ballots_null: "Invalid ballots" submit: "Save" results_list: "Your results" + see_results: "See results" + index: + no_results: "No results" + results: Results residence: flash: create: "Document verified with Census" diff --git a/config/locales/officing.es.yml b/config/locales/officing.es.yml index 645876309..c8c97b1c5 100644 --- a/config/locales/officing.es.yml +++ b/config/locales/officing.es.yml @@ -70,6 +70,10 @@ es: ballots_null: "Papeletas nulas" submit: "Guardar" results_list: "Tus resultados" + see_results: "Ver resultados" + index: + no_results: "No hay resultados" + results: "Resultados" residence: flash: create: "Documento verificado con el Padrón" diff --git a/config/routes.rb b/config/routes.rb index 2295453b6..41511ef97 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -336,7 +336,7 @@ Rails.application.routes.draw do resources :recounts, only: [:new, :create] resources :final_recounts, only: [:new, :create] - resources :results, only: [:new, :create] + resources :results, only: [:new, :create, :index] end resource :residence, controller: "residence", only: [:new, :create] resources :voters, only: [:new, :create] diff --git a/spec/features/officing/results_spec.rb b/spec/features/officing/results_spec.rb index b4129645b..141bcd687 100644 --- a/spec/features/officing/results_spec.rb +++ b/spec/features/officing/results_spec.rb @@ -72,4 +72,68 @@ feature 'Officing Results' do end end + scenario 'Edit result' do + partial_result = create(:poll_partial_result, + officer_assignment: @officer_assignment, + booth_assignment: @officer_assignment.booth_assignment, + date: @poll.starts_at, + question: @question_1, + answer: @question_1.valid_answers[0], + author: @poll_officer.user, + amount: 7777) + + visit officing_poll_results_path(@poll, date: I18n.l(partial_result.date), booth_assignment_id: partial_result.booth_assignment_id) + + expect(page).to have_content('7777') + + visit new_officing_poll_result_path(@poll) + + booth_name = partial_result.booth_assignment.booth.name + date = I18n.l(partial_result.date, format: :long) + select booth_name, from: 'officer_assignment_id' + select date, from: 'date' + + fill_in "questions[#{@question_1.id}][0]", with: '5555' + fill_in "questions[#{@question_1.id}][1]", with: '200' + + click_button 'Save' + + within("#results_#{partial_result.booth_assignment_id}_#{partial_result.date.strftime('%Y%m%d')}") do + expect(page).to have_content(I18n.l(partial_result.date, format: :long)) + expect(page).to have_content(partial_result.booth_assignment.booth.name) + click_link "See results" + end + + expect(page).to_not have_content('7777') + within("#question_#{@question_1.id}_0_result") { expect(page).to have_content('5555') } + within("#question_#{@question_1.id}_1_result") { expect(page).to have_content('200') } + end + + scenario 'Index lists all questions and answers' do + partial_result = create(:poll_partial_result, + officer_assignment: @officer_assignment, + booth_assignment: @officer_assignment.booth_assignment, + date: @poll.ends_at, + question: @question_1, + amount: 33) + + visit officing_poll_results_path(@poll, + date: I18n.l(@poll.ends_at.to_date), + booth_assignment_id: @officer_assignment.booth_assignment_id) + + expect(page).to have_content(I18n.l(@poll.ends_at.to_date, format: :long)) + expect(page).to have_content(@officer_assignment.booth_assignment.booth.name) + + expect(page).to have_content(@question_1.title) + @question_1.valid_answers.each_with_index do |answer, i| + within("#question_#{@question_1.id}_#{i}_result") { expect(page).to have_content(answer) } + end + + expect(page).to have_content(@question_2.title) + @question_2.valid_answers.each_with_index do |answer, i| + within("#question_#{@question_2.id}_#{i}_result") { expect(page).to have_content(answer) } + end + + end + end \ No newline at end of file From eed03d0e0efd62a7420cf00381cc4fd20bb96355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 2 Feb 2017 16:11:15 +0100 Subject: [PATCH 24/25] show existing results also on creation error --- app/controllers/officing/results_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb index e716b8c8b..76e4dff3e 100644 --- a/app/controllers/officing/results_controller.rb +++ b/app/controllers/officing/results_controller.rb @@ -72,6 +72,7 @@ class Officing::ResultsController < Officing::BaseController 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 From f060969422ee2e9596c44531db9de4f7ab02748c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baza=CC=81n?= Date: Thu, 2 Feb 2017 16:26:21 +0100 Subject: [PATCH 25/25] adds changes logging to poll partial results --- app/models/poll/partial_result.rb | 10 +++ ..._add_log_fields_to_poll_partial_results.rb | 7 ++ db/schema.rb | 5 +- spec/features/officing/results_spec.rb | 2 +- spec/models/poll/partial_result_spec.rb | 65 +++++++++++++++++++ 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20170202151151_add_log_fields_to_poll_partial_results.rb diff --git a/app/models/poll/partial_result.rb b/app/models/poll/partial_result.rb index 037395277..e42589a03 100644 --- a/app/models/poll/partial_result.rb +++ b/app/models/poll/partial_result.rb @@ -15,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 \ No newline at end of file diff --git a/db/migrate/20170202151151_add_log_fields_to_poll_partial_results.rb b/db/migrate/20170202151151_add_log_fields_to_poll_partial_results.rb new file mode 100644 index 000000000..86966aed4 --- /dev/null +++ b/db/migrate/20170202151151_add_log_fields_to_poll_partial_results.rb @@ -0,0 +1,7 @@ +class AddLogFieldsToPollPartialResults < ActiveRecord::Migration + def change + add_column :poll_partial_results, :amount_log, :text, default: "" + add_column :poll_partial_results, :officer_assignment_id_log, :text, default: "" + add_column :poll_partial_results, :author_id_log, :text, default: "" + end +end diff --git a/db/schema.rb b/db/schema.rb index 13ad1dce7..95028b472 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: 20170201113206) do +ActiveRecord::Schema.define(version: 20170202151151) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -433,6 +433,9 @@ ActiveRecord::Schema.define(version: 20170201113206) do t.date "date" t.integer "booth_assignment_id" t.integer "officer_assignment_id" + t.text "amount_log", default: "" + t.text "officer_assignment_id_log", default: "" + t.text "author_id_log", default: "" end add_index "poll_partial_results", ["answer"], name: "index_poll_partial_results_on_answer", using: :btree diff --git a/spec/features/officing/results_spec.rb b/spec/features/officing/results_spec.rb index 141bcd687..586ed387e 100644 --- a/spec/features/officing/results_spec.rb +++ b/spec/features/officing/results_spec.rb @@ -84,7 +84,7 @@ feature 'Officing Results' do visit officing_poll_results_path(@poll, date: I18n.l(partial_result.date), booth_assignment_id: partial_result.booth_assignment_id) - expect(page).to have_content('7777') + within("#question_#{@question_1.id}_0_result") { expect(page).to have_content('7777') } visit new_officing_poll_result_path(@poll) diff --git a/spec/models/poll/partial_result_spec.rb b/spec/models/poll/partial_result_spec.rb index 1d203862b..70651eda6 100644 --- a/spec/models/poll/partial_result_spec.rb +++ b/spec/models/poll/partial_result_spec.rb @@ -13,4 +13,69 @@ describe Poll::PartialResult do end end + describe "logging changes" do + it "should update amount_log if amount changes" do + partial_result = create(:poll_partial_result, amount: 33) + + expect(partial_result.amount_log).to eq("") + + partial_result.amount = 33 + partial_result.save + partial_result.amount = 32 + partial_result.save + partial_result.amount = 34 + partial_result.save + + expect(partial_result.amount_log).to eq(":33:32") + end + + it "should update officer_assignment_id_log if amount changes" do + partial_result = create(:poll_partial_result, amount: 33) + + expect(partial_result.amount_log).to eq("") + expect(partial_result.officer_assignment_id_log).to eq("") + + partial_result.amount = 33 + partial_result.officer_assignment_id = 1 + partial_result.save + + partial_result.amount = 32 + partial_result.officer_assignment_id = 2 + partial_result.save + + partial_result.amount = 34 + partial_result.officer_assignment_id = 3 + partial_result.save + + expect(partial_result.amount_log).to eq(":33:32") + expect(partial_result.officer_assignment_id_log).to eq(":1:2") + end + + it "should update author_id if amount changes" do + partial_result = create(:poll_partial_result, amount: 33) + + expect(partial_result.amount_log).to eq("") + expect(partial_result.author_id_log).to eq("") + + author_A = create(:poll_officer).user + author_B = create(:poll_officer).user + author_C = create(:poll_officer).user + + partial_result.amount = 33 + partial_result.author_id = author_A.id + partial_result.save! + + partial_result.amount = 32 + partial_result.author_id = author_B.id + partial_result.save! + + partial_result.amount = 34 + partial_result.author_id = author_C.id + partial_result.save! + + expect(partial_result.amount_log).to eq(":33:32") + expect(partial_result.author_id_log).to eq(":#{author_A.id}:#{author_B.id}") + end + end + end