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

View File

@@ -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
@@ -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,28 @@ en:
submit: Save
final_recount_list: "Your final recounts"
system_count: "System recount"
add_results: "Add results"
results:
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"
booth: "Booth"
date: "Date"
select_booth: "Select booth"
select_date: "Select date"
ballots_blank: "Blank ballots"
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"

View File

@@ -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,28 @@ es:
submit: "Guardar"
final_recount_list: "Tus recuentos finales"
system_count: "Recuento del sistema"
add_results: "Añadir resultados"
results:
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"
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"
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"

View File

@@ -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, :index]
end
resource :residence, controller: "residence", only: [:new, :create]
resources :voters, only: [:new, :create]

View File

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

View File

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

View File

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

View File

@@ -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: 20170202151151) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -430,10 +430,17 @@ 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"
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
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

View File

@@ -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,10 +40,13 @@ feature 'Officing Final Recount' do
visit officing_root_path
within('#side_menu') do
click_link 'Final recounts'
click_link 'Final recounts and results'
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')
@@ -119,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

View File

@@ -0,0 +1,139 @@
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
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)
within("#question_#{@question_1.id}_0_result") { 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

View File

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