diff --git a/app/models/poll/officer_assignment.rb b/app/models/poll/officer_assignment.rb index 9fcf02890..417e6a150 100644 --- a/app/models/poll/officer_assignment.rb +++ b/app/models/poll/officer_assignment.rb @@ -8,7 +8,7 @@ class Poll validates :officer_id, presence: true validates :booth_assignment_id, presence: true - validates :date, presence: true, uniqueness: { scope: [:officer_id, :booth_assignment_id] } + validates :date, presence: true delegate :poll_id, :booth_id, to: :booth_assignment diff --git a/app/models/poll/shift.rb b/app/models/poll/shift.rb index d64bce9ac..4edeb26ef 100644 --- a/app/models/poll/shift.rb +++ b/app/models/poll/shift.rb @@ -5,28 +5,37 @@ class Poll validates :booth_id, presence: true validates :officer_id, presence: true - validates :date, presence: true - validates :date, uniqueness: { scope: [:officer_id, :booth_id] } + validates :date, presence: true, uniqueness: { scope: [:officer_id, :booth_id, :task] } validates :task, presence: true enum task: { vote_collection: 0, recount_scrutiny: 1 } before_create :persist_data after_create :create_officer_assignments - - def create_officer_assignments - booth.booth_assignments.each do |booth_assignment| - attrs = { officer_id: officer_id, - date: date, - booth_assignment_id: booth_assignment.id } - Poll::OfficerAssignment.create!(attrs) - end - end + before_destroy :destroy_officer_assignments def persist_data self.officer_name = officer.name self.officer_email = officer.email end + def create_officer_assignments + booth.booth_assignments.each do |booth_assignment| + attrs = { + officer_id: officer_id, + date: date, + booth_assignment_id: booth_assignment.id, + final: recount_scrutiny? + } + Poll::OfficerAssignment.create!(attrs) + end + end + + def destroy_officer_assignments + Poll::OfficerAssignment.where(booth_assignment: booth.booth_assignments, + officer: officer, + date: date, + final: recount_scrutiny?).destroy_all + end end end diff --git a/db/migrate/20171002103314_add_poll_shift_task_index.rb b/db/migrate/20171002103314_add_poll_shift_task_index.rb new file mode 100644 index 000000000..d15275556 --- /dev/null +++ b/db/migrate/20171002103314_add_poll_shift_task_index.rb @@ -0,0 +1,7 @@ +class AddPollShiftTaskIndex < ActiveRecord::Migration + def change + remove_index "poll_shifts", name: "index_poll_shifts_on_booth_id_and_officer_id" + add_index :poll_shifts, :task + add_index :poll_shifts, [:booth_id, :officer_id, :task], unique: true + end +end diff --git a/db/migrate/20171003095936_remove_officer_assigment_composed_index.rb b/db/migrate/20171003095936_remove_officer_assigment_composed_index.rb new file mode 100644 index 000000000..874672f84 --- /dev/null +++ b/db/migrate/20171003095936_remove_officer_assigment_composed_index.rb @@ -0,0 +1,5 @@ +class RemoveOfficerAssigmentComposedIndex < ActiveRecord::Migration + def change + remove_index "poll_officer_assignments", name: "index_poll_officer_assignments_on_officer_id_and_date" + end +end diff --git a/db/schema.rb b/db/schema.rb index af121fa0e..e75c2aac3 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: 20171002191347) do +ActiveRecord::Schema.define(version: 20171003095936) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -639,7 +639,6 @@ ActiveRecord::Schema.define(version: 20171002191347) do end add_index "poll_officer_assignments", ["booth_assignment_id"], name: "index_poll_officer_assignments_on_booth_assignment_id", using: :btree - add_index "poll_officer_assignments", ["officer_id", "date"], name: "index_poll_officer_assignments_on_officer_id_and_date", using: :btree add_index "poll_officer_assignments", ["officer_id"], name: "index_poll_officer_assignments_on_officer_id", using: :btree create_table "poll_officers", force: :cascade do |t| @@ -720,9 +719,10 @@ ActiveRecord::Schema.define(version: 20171002191347) do t.integer "task", default: 0, null: false end - add_index "poll_shifts", ["booth_id", "officer_id"], name: "index_poll_shifts_on_booth_id_and_officer_id", using: :btree + add_index "poll_shifts", ["booth_id", "officer_id", "task"], name: "index_poll_shifts_on_booth_id_and_officer_id_and_task", unique: true, using: :btree add_index "poll_shifts", ["booth_id"], name: "index_poll_shifts_on_booth_id", using: :btree add_index "poll_shifts", ["officer_id"], name: "index_poll_shifts_on_officer_id", using: :btree + add_index "poll_shifts", ["task"], name: "index_poll_shifts_on_task", using: :btree create_table "poll_total_results", force: :cascade do |t| t.integer "author_id" diff --git a/spec/features/admin/poll/shifts_spec.rb b/spec/features/admin/poll/shifts_spec.rb index 46c737c64..2e957ef11 100644 --- a/spec/features/admin/poll/shifts_spec.rb +++ b/spec/features/admin/poll/shifts_spec.rb @@ -30,12 +30,12 @@ feature 'Admin shifts' do expect(page).to have_content officer.name end - scenario "Create Vote Collection Shift", :js do + scenario "Create Vote Collection Shift and Recount & Scrutiny Shift on same date", :js do poll = create(:poll) - vote_collection_dates = (poll.starts_at.to_date..poll.ends_at.to_date).to_a.map { |date| I18n.l(date, format: :long) } - booth = create(:poll_booth) officer = create(:poll_officer) + vote_collection_dates = (poll.starts_at.to_date..poll.ends_at.to_date).to_a.map { |date| I18n.l(date, format: :long) } + recount_scrutiny_dates = (poll.ends_at.to_date..poll.ends_at.to_date + 1.week).to_a.map { |date| I18n.l(date, format: :long) } visit admin_booths_path @@ -60,14 +60,6 @@ feature 'Admin shifts' do expect(page).to have_content("Collect Votes") expect(page).to have_content(officer.name) end - end - - scenario "Create Recount & Scrutiny Shift", :js do - poll = create(:poll) - recount_scrutiny_dates = (poll.ends_at.to_date..poll.ends_at.to_date + 1.week).to_a.map { |date| I18n.l(date, format: :long) } - - booth = create(:poll_booth) - officer = create(:poll_officer) visit admin_booths_path @@ -89,7 +81,7 @@ feature 'Admin shifts' do expect(page).to have_content "Shift added" within("#shifts") do - expect(page).to have_css(".shift", count: 1) + expect(page).to have_css(".shift", count: 2) expect(page).to have_content(I18n.l(poll.ends_at.to_date + 4.days, format: :long)) expect(page).to have_content("Recount & Scrutiny") expect(page).to have_content(officer.name) diff --git a/spec/models/poll/shift_spec.rb b/spec/models/poll/shift_spec.rb index b7918b95c..b62f220da 100644 --- a/spec/models/poll/shift_spec.rb +++ b/spec/models/poll/shift_spec.rb @@ -28,7 +28,7 @@ describe :shift do describe "officer_assignments" do - it "should create corresponding officer_assignments" do + it "should create and destroy corresponding officer_assignments" do poll1 = create(:poll) poll2 = create(:poll) poll3 = create(:poll) @@ -39,21 +39,45 @@ describe :shift do booth_assignment1 = create(:poll_booth_assignment, poll: poll1, booth: booth) booth_assignment2 = create(:poll_booth_assignment, poll: poll2, booth: booth) - shift = create(:poll_shift, booth: booth, officer: officer, date: Date.current) + expect { create(:poll_shift, booth: booth, officer: officer, date: Date.current) }.to change {Poll::OfficerAssignment.all.count}.by(2) officer_assignments = Poll::OfficerAssignment.all - expect(officer_assignments.count).to eq(2) - oa1 = officer_assignments.first oa2 = officer_assignments.second expect(oa1.officer).to eq(officer) expect(oa1.date).to eq(Date.current) expect(oa1.booth_assignment).to eq(booth_assignment1) + expect(oa1.final).to be_falsey expect(oa2.officer).to eq(officer) expect(oa2.date).to eq(Date.current) expect(oa2.booth_assignment).to eq(booth_assignment2) + expect(oa2.final).to be_falsey + + create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment1, date: Date.tomorrow) + + expect { Poll::Shift.last.destroy }.to change {Poll::OfficerAssignment.all.count}.by(-2) + end + + it "should create final officer_assignments" do + poll = create(:poll) + booth = create(:poll_booth) + officer = create(:poll_officer) + + booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth) + + shift = create(:poll_shift, booth: booth, officer: officer, date: Date.current, task: :recount_scrutiny) + + officer_assignments = Poll::OfficerAssignment.all + expect(officer_assignments.count).to eq(1) + + officer_assignment = officer_assignments.first + + expect(officer_assignment.officer).to eq(officer) + expect(officer_assignment.date).to eq(Date.current) + expect(officer_assignment.booth_assignment).to eq(booth_assignment) + expect(officer_assignment.final).to be_truthy end end