diff --git a/app/models/poll/recount.rb b/app/models/poll/recount.rb new file mode 100644 index 000000000..97a909d1f --- /dev/null +++ b/app/models/poll/recount.rb @@ -0,0 +1,36 @@ +class Poll::Recount < ActiveRecord::Base + + VALID_ORIGINS = %w{ web booth letter } + + belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' + belongs_to :booth_assignment + belongs_to :officer_assignment + + validates :author, presence: true + validates :origin, inclusion: {in: VALID_ORIGINS} + + scope :web, -> { where(origin: 'web') } + scope :booth, -> { where(origin: 'booth') } + scope :letter, -> { where(origin: 'letter') } + + scope :by_author, ->(author_id) { where(author_id: author_id) } + + before_save :update_logs + + def update_logs + amounts_changed = false + + [:white, :null, :total].each do |amount| + next unless send("#{amount}_amount_changed?") && send("#{amount}_amount_was").present? + self["#{amount}_amount_log"] += ":#{send("#{amount}_amount_was").to_s}" + amounts_changed = true + end + + update_officer_author if amounts_changed + end + + def update_officer_author + self.officer_assignment_id_log += ":#{officer_assignment_id_was.to_s}" + self.author_id_log += ":#{author_id_was.to_s}" + end +end diff --git a/db/migrate/20171002122312_create_poll_recount.rb b/db/migrate/20171002122312_create_poll_recount.rb new file mode 100644 index 000000000..807f1c84e --- /dev/null +++ b/db/migrate/20171002122312_create_poll_recount.rb @@ -0,0 +1,24 @@ +class CreatePollRecount < ActiveRecord::Migration + def change + create_table :poll_recounts do |t| + t.integer :author_id + t.string :origin + t.date :date + t.integer :booth_assignment_id + t.integer :officer_assignment_id + t.text :officer_assignment_id_log, default: "" + t.text :author_id_log, default: "" + t.integer :white_amount + t.text :white_amount_log, default: "" + t.integer :null_amount + t.text :null_amount_log, default: "" + t.integer :total_amount + t.text :total_amount_log, default: "" + end + + add_index :poll_recounts, :booth_assignment_id + add_index :poll_recounts, :officer_assignment_id + add_foreign_key :poll_recounts, :poll_booth_assignments, column: :booth_assignment_id + add_foreign_key :poll_recounts, :poll_officer_assignments, column: :officer_assignment_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 500f03540..e859a487f 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: 20170927110953) do +ActiveRecord::Schema.define(version: 20171002122312) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -690,6 +690,25 @@ ActiveRecord::Schema.define(version: 20170927110953) do add_index "poll_questions", ["proposal_id"], name: "index_poll_questions_on_proposal_id", using: :btree add_index "poll_questions", ["tsv"], name: "index_poll_questions_on_tsv", using: :gin + create_table "poll_recounts", force: :cascade do |t| + t.integer "author_id" + t.string "origin" + t.date "date" + t.integer "booth_assignment_id" + t.integer "officer_assignment_id" + t.text "officer_assignment_id_log", default: "" + t.text "author_id_log", default: "" + t.integer "white_amount" + t.text "white_amount_log", default: "" + t.integer "null_amount" + t.text "null_amount_log", default: "" + t.integer "total_amount" + t.text "total_amount_log", default: "" + end + + add_index "poll_recounts", ["booth_assignment_id"], name: "index_poll_recounts_on_booth_assignment_id", using: :btree + add_index "poll_recounts", ["officer_assignment_id"], name: "index_poll_recounts_on_officer_assignment_id", using: :btree + create_table "poll_shifts", force: :cascade do |t| t.integer "booth_id" t.integer "officer_id" @@ -1126,6 +1145,8 @@ ActiveRecord::Schema.define(version: 20170927110953) do add_foreign_key "poll_questions", "polls" add_foreign_key "poll_questions", "proposals" add_foreign_key "poll_questions", "users", column: "author_id" + add_foreign_key "poll_recounts", "poll_booth_assignments", column: "booth_assignment_id" + add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id" add_foreign_key "poll_voters", "polls" add_foreign_key "poll_white_results", "poll_booth_assignments", column: "booth_assignment_id" add_foreign_key "poll_white_results", "poll_officer_assignments", column: "officer_assignment_id" diff --git a/spec/factories.rb b/spec/factories.rb index b0a287aea..30159f85a 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -569,6 +569,11 @@ FactoryGirl.define do origin { 'web' } end + factory :poll_recount, class: 'Poll::Recount' do + association :author, factory: :user + origin { 'web' } + end + factory :officing_residence, class: 'Officing::Residence' do user association :officer, factory: :poll_officer diff --git a/spec/models/poll/recount_spec.rb b/spec/models/poll/recount_spec.rb new file mode 100644 index 000000000..1ca0b41eb --- /dev/null +++ b/spec/models/poll/recount_spec.rb @@ -0,0 +1,102 @@ +require 'rails_helper' + +describe Poll::Recount do + + describe "logging changes" do + let(:poll_recount) { create(:poll_recount) } + + it "should update white_amount_log if white_amount changes" do + poll_recount.white_amount = 33 + + expect(poll_recount.white_amount_log).to eq("") + + poll_recount.white_amount = 33 + poll_recount.save + poll_recount.white_amount = 32 + poll_recount.save + poll_recount.white_amount = 34 + poll_recount.save + + expect(poll_recount.white_amount_log).to eq(":33:32") + end + + it "should update null_amount_log if null_amount changes" do + poll_recount.null_amount = 33 + + expect(poll_recount.null_amount_log).to eq("") + + poll_recount.null_amount = 33 + poll_recount.save + poll_recount.null_amount = 32 + poll_recount.save + poll_recount.null_amount = 34 + poll_recount.save + + expect(poll_recount.null_amount_log).to eq(":33:32") + end + + it "should update total_amount_log if total_amount changes" do + poll_recount.total_amount = 33 + + expect(poll_recount.total_amount_log).to eq("") + + poll_recount.total_amount = 33 + poll_recount.save + poll_recount.total_amount = 32 + poll_recount.save + poll_recount.total_amount = 34 + poll_recount.save + + expect(poll_recount.total_amount_log).to eq(":33:32") + end + + it "should update officer_assignment_id_log if amount changes" do + poll_recount.white_amount = 33 + + expect(poll_recount.white_amount_log).to eq("") + expect(poll_recount.officer_assignment_id_log).to eq("") + + poll_recount.white_amount = 33 + poll_recount.officer_assignment = create(:poll_officer_assignment, id: 101) + poll_recount.save + + poll_recount.white_amount = 32 + poll_recount.officer_assignment = create(:poll_officer_assignment, id: 102) + poll_recount.save + + poll_recount.white_amount = 34 + poll_recount.officer_assignment = create(:poll_officer_assignment, id: 103) + poll_recount.save + + expect(poll_recount.white_amount_log).to eq(":33:32") + expect(poll_recount.officer_assignment_id_log).to eq(":101:102") + end + + it "should update author_id if amount changes" do + poll_recount.white_amount = 33 + + expect(poll_recount.white_amount_log).to eq("") + expect(poll_recount.author_id_log).to eq("") + + author_A = create(:poll_officer).user + author_B = create(:poll_officer).user + author_C = create(:poll_officer).user + + poll_recount.white_amount = 33 + poll_recount.author_id = author_A.id + poll_recount.save! + + poll_recount.white_amount = 32 + poll_recount.author_id = author_B.id + poll_recount.save! + + poll_recount.white_amount = 34 + poll_recount.author_id = author_C.id + poll_recount.save! + + expect(poll_recount.white_amount_log).to eq(":33:32") + expect(poll_recount.author_id_log).to eq(":#{author_A.id}:#{author_B.id}") + end + end + +end