diff --git a/app/controllers/incidents_controller.rb b/app/controllers/incidents_controller.rb index c08a96c0..bb1056c9 100644 --- a/app/controllers/incidents_controller.rb +++ b/app/controllers/incidents_controller.rb @@ -52,7 +52,11 @@ def create if @incident.save @incident.notify_supervisor_of_new_report if @assigning_supervisor @incident.remove_supervisor if @removing_supervisor - redirect_to incidents_path, notice: 'Incident was successfully created.' + if current_user.driver? + redirect_to edit_incident_path(@incident) + else + redirect_to incidents_path, notice: 'Incident was successfully created.' + end else render :new, status: :unprocessable_entity end end @@ -102,11 +106,7 @@ def index end def new - if current_user.driver? - @incident = Incident.create driver_incident_report_attributes: { user_id: current_user.id } - redirect_to edit_incident_path(@incident) - else @incident = Incident.new - end + @incident = Incident.new end def search @@ -166,6 +166,10 @@ def update def incident_params data = params.require(:incident).permit! sup_report_attrs = data[:supervisor_incident_report_attributes] + if current_user.driver? + data[:driver_incident_report_attributes] = { "user_id" => current_user.id } + @incident.driver_incident_report = IncidentReport.new + end if sup_report_attrs.present? @assigning_supervisor = sup_report_attrs[:user_id].present? && @incident.supervisor_report.nil? diff --git a/app/models/incident.rb b/app/models/incident.rb index 4bf3bc34..ee4ddf4e 100644 --- a/app/models/incident.rb +++ b/app/models/incident.rb @@ -22,6 +22,7 @@ class Incident < ApplicationRecord # belongs_to :reason_code, optional: { unless: :completed? } belongs_to :reason_code, optional: true belongs_to :supplementary_reason_code, optional: true + validates :occurred_at, presence: true validates :reason_code, :supplementary_reason_code, :root_cause_analysis, :latitude, :longitude, presence: true, if: :completed? @@ -31,17 +32,13 @@ class Incident < ApplicationRecord validate :supervisor_in_correct_group accepts_nested_attributes_for :driver_incident_report - validates :occurred_at, presence: true, on: :create, if: :created_by_supervisor - delegate :occurred_at_readable, to: :driver_incident_report - delegate :occurred_at, to: :driver_incident_report accepts_nested_attributes_for :supervisor_incident_report accepts_nested_attributes_for :supervisor_report has_many :staff_reviews, dependent: :destroy scope :between, (lambda do |start_date, end_date| - joins(:driver_incident_report) - .where incident_reports: { occurred_at: start_date..end_date } + where occurred_at: start_date..end_date end) scope :in_divisions, (lambda do |divisions| @@ -50,7 +47,7 @@ class Incident < ApplicationRecord end) scope :occurred_order, (lambda do - joins(:driver_incident_report).order 'incident_reports.occurred_at' + order :occurred_at end) scope :for_driver, ->(user) { @@ -72,6 +69,18 @@ class Incident < ApplicationRecord after_create :send_notifications + def occurred_at_readable + [occurred_date, occurred_time].join ' - ' + end + + def occurred_date + occurred_at.try :strftime, '%A, %B %e' + end + + def occurred_time + occurred_at.try :strftime, '%l:%M %P' + end + def claim_for(user) self.supervisor_incident_report = create_supervisor_incident_report user: user self.supervisor_report = create_supervisor_report @@ -81,10 +90,10 @@ def claim_for(user) def csv_row row = [] report = driver_incident_report - row << report.occurred_at.strftime('%m/%d/%Y') # Date + row << occurred_at.strftime('%m/%d/%Y') # Date row << report.bus # Bus row << "#{driver.badge_number} | #{driver.proper_name.upcase}" # Badge # and Operator - row << report.occurred_at.strftime('%H:%M:%S') # Time + row << occurred_at.strftime('%H:%M:%S') # Time row << report.full_location # Location row << report.run # Route row << reason_code.try(:identifier) || "" # Classification 1 @@ -111,7 +120,7 @@ def export_claims_xml(current_user) builder = Nokogiri::XML::Builder.new do |doc| doc.claims_incident_data do doc.drivers_report do - doc.incident_date report.occurred_at.iso8601 + doc.incident_date occurred_at.iso8601 doc.street report.location doc.city report.town doc.state report.state diff --git a/app/models/incident_report.rb b/app/models/incident_report.rb index 139cb97c..76edbb53 100644 --- a/app/models/incident_report.rb +++ b/app/models/incident_report.rb @@ -52,7 +52,7 @@ class IncidentReport < ApplicationRecord accepts_nested_attributes_for :injured_passengers - validates :occurred_at, :location, :direction, :town, :bus, :description, + validates :location, :direction, :town, :bus, :description, presence: true, if: :changed?, unless: :new_record? validates :run, length: { maximum: 5 } validates :location, length: { maximum: 50 } @@ -95,18 +95,6 @@ def needs_reason_not_up_to_curb? motion_of_bus == 'Stopped' && !bus_up_to_curb? end - def occurred_at_readable - [occurred_date, occurred_time].join ' - ' - end - - def occurred_date - occurred_at.try :strftime, '%A, %B %e' - end - - def occurred_time - occurred_at.try :strftime, '%l:%M %P' - end - # rubocop:disable Metrics/LineLength def other_vehicle_driver_full_address first_line = other_vehicle_driver_address diff --git a/app/views/incident_reports/_form.html.haml b/app/views/incident_reports/_form.html.haml index 11f2210a..cc9c40f3 100644 --- a/app/views/incident_reports/_form.html.haml +++ b/app/views/incident_reports/_form.html.haml @@ -19,12 +19,6 @@ = form.select :user_id, options_from_collection_for_select(users, :id, :proper_name, report.user_id), { include_blank: true }, id: :incident_report_user_id - .field - = form.label :occurred_at - - a11y_datetime_labels('incident_report_occurred_at').each do |label| - = label - = form.datetime_select :occurred_at, id: :incident_report_occurred_at, - prompt: true, ampm: true .field = form.label :run = form.text_field :run, id: :incident_report_run diff --git a/app/views/incident_reports/_show.haml b/app/views/incident_reports/_show.haml index 5e928e9c..7c179634 100644 --- a/app/views/incident_reports/_show.haml +++ b/app/views/incident_reports/_show.haml @@ -29,9 +29,6 @@ %p %strong= human_name :incident, :bus = report.bus -%p - %strong= human_name :incident_report, :occurred_at - = report.occurred_at_readable %p %strong= human_name :incident_report, :passengers_onboard = report.passengers_onboard diff --git a/app/views/incidents/_incident.xml.haml b/app/views/incidents/_incident.xml.haml index 2adec492..42454395 100644 --- a/app/views/incidents/_incident.xml.haml +++ b/app/views/incidents/_incident.xml.haml @@ -6,10 +6,10 @@ %ai_code= incident.reason_code.identifier - if incident.root_cause_analysis.present? %ai_commentary= incident.root_cause_analysis - - if report.occurred_at.present? - %ai_date_occured= report.occurred_at.strftime '%Y-%m-%d' - %ai_time_occured= report.occurred_at.strftime '2000-01-01T%H:%M:00.000' - %ai_occured_year= report.occurred_at.year + - if incident.occurred_at.present? + %ai_date_occured= incident.occurred_at.strftime '%Y-%m-%d' + %ai_time_occured= incident.occurred_at.strftime '2000-01-01T%H:%M:00.000' + %ai_occured_year= incident.occurred_at.year - if report.direction.present? && report.direction != 'NA' %ai_direction= report.direction - if report.town.present? diff --git a/app/views/incidents/new.html.haml b/app/views/incidents/new.html.haml index aecc9c24..a0ccedf7 100644 --- a/app/views/incidents/new.html.haml +++ b/app/views/incidents/new.html.haml @@ -9,25 +9,26 @@ - @incident.errors.full_messages.each do |message| %li= message = form_with model: @incident, local: true do |form| - = form.fields_for :driver_incident_report, IncidentReport.new do |driver_form| - .field - = driver_form.label :user_id, 'Driver' - = driver_form.select :user_id, - options_from_collection_for_select(@drivers, :id, :proper_name, current_user.id), - { include_blank: true }, - id: :incident_driver_incident_report_attributes_user_id - .field - = driver_form.label :occurred_at - - a11y_datetime_labels('incident_driver_incident_report_attributes_occurred_at').each do |label| - = label - = driver_form.datetime_select :occurred_at, id: :incident_driver_incident_report_attributes_occurred_at, - prompt: true, ampm: true - = form.fields_for :supervisor_incident_report, IncidentReport.new do |supervisor_form| - .field - = supervisor_form.label :user_id, 'Supervisor' - = supervisor_form.select :user_id, - options_from_collection_for_select(@supervisors, :id, :proper_name, current_user.id), - { include_blank: true }, - id: :incident_supervisor_incident_report_attributes_user_id + .field + = form.label :occurred_at + - a11y_datetime_labels('incident_occurred_at').each do |label| + = label + = form.datetime_select :occurred_at, id: :incident_occurred_at, + prompt: true, ampm: true + - unless current_user.driver? + = form.fields_for :driver_incident_report, IncidentReport.new do |driver_form| + .field + = driver_form.label :user_id, 'Driver' + = driver_form.select :user_id, + options_from_collection_for_select(@drivers, :id, :proper_name, current_user.id), + { include_blank: true }, + id: :incident_driver_incident_report_attributes_user_id + = form.fields_for :supervisor_incident_report, IncidentReport.new do |supervisor_form| + .field + = supervisor_form.label :user_id, 'Supervisor' + = supervisor_form.select :user_id, + options_from_collection_for_select(@supervisors, :id, :proper_name, current_user.id), + { include_blank: true }, + id: :incident_supervisor_incident_report_attributes_user_id .actions= form.submit 'Create Incident Report' = link_to 'Back', incidents_path diff --git a/app/views/incidents/show.html.haml b/app/views/incidents/show.html.haml index 3950b974..1e806198 100644 --- a/app/views/incidents/show.html.haml +++ b/app/views/incidents/show.html.haml @@ -16,6 +16,9 @@ %p %strong= human_name :incident, :completed = yes_no_image @incident.completed? + %p + %strong= human_name :incident, :occurred_at + = @incident.occurred_at_readable - if @incident.completed? && @incident.valid? %p diff --git a/app/views/incidents/show.pdf.prawn b/app/views/incidents/show.pdf.prawn index b2176ad7..e5635783 100644 --- a/app/views/incidents/show.pdf.prawn +++ b/app/views/incidents/show.pdf.prawn @@ -36,8 +36,8 @@ prawn_document do |pdf| end pdf.field_row height: 30, units: 6 do |row| - row.text_field field: 'Date of Incident', value: report.occurred_at.try(:strftime, '%m/%d/%Y') - row.text_field field: 'Time of Incident', value: report.occurred_time + row.text_field field: 'Date of Incident', value: @incident.occurred_at.try(:strftime, '%m/%d/%Y') + row.text_field field: 'Time of Incident', value: @incident.occurred_time row.text_field field: '# passengers on bus', value: report.passengers_onboard row.text_field field: '# courtesy cards distributed', value: report.courtesy_cards_distributed row.text_field field: '# courtesy cards attached', value: report.courtesy_cards_collected @@ -217,7 +217,7 @@ prawn_document do |pdf| row.text_field width: 4, field: 'Operator', value: report.user.proper_name row.text_field field: 'Badge No.', value: report.user.badge_number row.text_field field: 'Bus #', value: report.bus - row.text_field width: 2, field: 'Date of Incident', value: report.occurred_at.try(:strftime, '%m/%d/%Y') + row.text_field width: 2, field: 'Date of Incident', value: @incident.occurred_at.try(:strftime, '%m/%d/%Y') end pdf.field_row height: pdf.cursor - 30, units: 1 do |row| @@ -279,8 +279,8 @@ prawn_document do |pdf| end pdf.field_row height: 30, units: 7 do |row| - row.text_field field: 'Date of Incident', value: report.occurred_at.try(:strftime, '%m/%d/%Y') - row.text_field field: 'Time of Incident', value: report.occurred_time + row.text_field field: 'Date of Incident', value: @incident.occurred_at.try(:strftime, '%m/%d/%Y') + row.text_field field: 'Time of Incident', value: @incident.occurred_time row.text_field field: '# passengers on bus', value: report.passengers_onboard row.text_field field: '# courtesy cards distributed', value: report.courtesy_cards_distributed row.text_field field: '# courtesy cards attached', value: report.courtesy_cards_collected @@ -480,7 +480,7 @@ prawn_document do |pdf| value: @incident.driver.proper_name, options: { valign: :center } row.text_field field: 'Date and time of incident', width: 2, - value: report.occurred_at.try(:strftime, '%B %e, %Y %-l:%M %P'), + value: @incident.occurred_at.try(:strftime, '%B %e, %Y %-l:%M %P'), options: { valign: :center } row.text_field field: 'Location of incident', width: 1, value: report.location, diff --git a/config/locales/en.yml b/config/locales/en.yml index 5819016c..6454a279 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -14,7 +14,6 @@ en: block: 'Block #' bus: 'Bus #' zip: 'ZIP' - occurred_at: 'Date and time of incident' speed: 'Speed at time of incident' motor_vehicle_collision?: 'Did the incident involve a collision?' passenger_incident?: 'Did the incident involve a passenger?' diff --git a/db/migrate/20201230173222_add_occurred_at_to_incidents.rb b/db/migrate/20201230173222_add_occurred_at_to_incidents.rb new file mode 100644 index 00000000..abc3d91c --- /dev/null +++ b/db/migrate/20201230173222_add_occurred_at_to_incidents.rb @@ -0,0 +1,5 @@ +class AddOccurredAtToIncidents < ActiveRecord::Migration[5.2] + def change + add_column :incidents, :occurred_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index d013de19..e48b14b3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -143,6 +143,7 @@ t.integer "claims_id" t.boolean "exported_to_claims" t.integer "supplementary_reason_code_id" + t.datetime "occurred_at" end create_table "injured_passengers", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci", force: :cascade do |t| @@ -233,7 +234,7 @@ t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end - create_table "versions", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| + create_table "versions", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "item_type", limit: 191, null: false t.integer "item_id", null: false t.string "event", null: false diff --git a/lib/tasks/occurred_at.rake b/lib/tasks/occurred_at.rake new file mode 100644 index 00000000..4a5b5711 --- /dev/null +++ b/lib/tasks/occurred_at.rake @@ -0,0 +1,11 @@ +namespace :incidents do + desc 'move occurred_at to incidents' + task move_occurred_at: :environment do + Incident.all.each do |incident| + if incident.driver_incident_report? + occurred_at = incident.driver_incident_report.occurred_at + incident.update(occurred_at: occurred_at) + end + end + end +end diff --git a/spec/factories/incident_reports.rb b/spec/factories/incident_reports.rb index db049f13..8579c2f0 100644 --- a/spec/factories/incident_reports.rb +++ b/spec/factories/incident_reports.rb @@ -21,7 +21,6 @@ road_conditions { IncidentReport::ROAD_OPTIONS.sample } light_conditions { IncidentReport::LIGHT_OPTIONS.sample } description { FFaker::Lorem.paragraphs(5).join "\n" } - occurred_at { DateTime.now.beginning_of_minute } trait :driver_report do association :user, factory: %i[user driver] diff --git a/spec/factories/incidents.rb b/spec/factories/incidents.rb index 33a4c907..7fb483ce 100644 --- a/spec/factories/incidents.rb +++ b/spec/factories/incidents.rb @@ -2,6 +2,7 @@ FactoryBot.define do factory :incident do + occurred_at { DateTime.now.beginning_of_minute } association :driver_incident_report, factory: %i[incident_report driver_report] diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 67272dbb..82f92a8f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -63,7 +63,6 @@ end def fill_in_base_incident_fields - fill_in_date_and_time fill_in 'Bus #', with: '1803' fill_in 'Location', with: 'Mill and Locust' fill_in 'ZIP', with: '01108' diff --git a/spec/system/drivers/creating_incidents_spec.rb b/spec/system/drivers/creating_incidents_spec.rb index 84f11105..981dd71a 100644 --- a/spec/system/drivers/creating_incidents_spec.rb +++ b/spec/system/drivers/creating_incidents_spec.rb @@ -4,20 +4,30 @@ describe 'creating incidents as a driver' do before(:each) { when_current_user_is :driver } - it 'brings drivers directly to the form', js: true do - visit incidents_path + let :new_incident do + visit new_incident_url + fill_in_date_and_time + click_on 'Create Incident Report' + end + it 'prompts to input the date before redirecting to driver report', js: true do + visit incidents_url find('button', text: 'New Incident').click + expect(page).to have_text 'New Incident' + click_on 'Create Incident Report' + expect(page).to have_text "Date and time of incident can't be blank" + fill_in_date_and_time + click_on 'Create Incident Report' expect(page).to have_text 'Editing Driver Account of Incident' driver_report = Incident.last.driver_incident_report expect(page).to have_current_path edit_incident_report_path(driver_report) end + it 'requires base fields', js: true do - visit new_incident_path + new_incident save_and_preview - expect(page).to have_text 'This incident report has 6 missing values and so cannot be marked as completed.' - expect(page).to have_text "Date and time of incident can't be blank" + expect(page).to have_text 'This incident report has 5 missing values and so cannot be marked as completed.' expect(page).to have_text "Location can't be blank" expect(page).to have_text "Town can't be blank" expect(page).to have_text "Bus # can't be blank" @@ -26,7 +36,7 @@ end it 'only requires bus, location, and town', js: true do - visit new_incident_path + new_incident fill_in_base_incident_fields save_and_preview diff --git a/spec/system/drivers/special_incident_fields_spec.rb b/spec/system/drivers/special_incident_fields_spec.rb index 8ba6597a..58ee48c5 100644 --- a/spec/system/drivers/special_incident_fields_spec.rb +++ b/spec/system/drivers/special_incident_fields_spec.rb @@ -5,11 +5,16 @@ describe 'special incident fields' do let(:driver) { create :user, :driver } before(:each) { when_current_user_is driver } + let :create_new_incident do + visit new_incident_url + fill_in_date_and_time + click_on 'Create Incident Report' + end describe 'collision related fields' do context 'without collision' do before :each do - visit new_incident_path + create_new_incident end it 'allows filling in collision fields', js: true do expect(page).not_to have_text 'Motor Vehicle Collision Information' @@ -43,7 +48,7 @@ describe 'other vehicle related fields' do context 'without other vehicle info' do it 'allows filling in other vehicle info as necessary', js: true do - visit new_incident_path + create_new_incident check 'Did the incident involve a collision?' expect(page).to have_field 'Other vehicle owner name' check 'Is the other driver involved the owner of the vehicle?' @@ -69,7 +74,7 @@ describe 'police related fields' do context 'without police info' do before :each do - visit new_incident_path + create_new_incident end it 'allows filling in police info', js: true do check 'Did the incident involve a collision?' @@ -106,7 +111,7 @@ describe 'passenger incident related fields' do context 'without passenger incidents' do before :each do - visit new_incident_path + create_new_incident end it 'allows filling in passenger incident fields', js: true do expect(page).not_to have_text 'Passenger Incident Information' @@ -139,7 +144,7 @@ describe 'reason not up to curb related fields' do before :each do - visit new_incident_path + create_new_incident end context 'without reason not up to curb' do it 'allows filling in reason bus was not up to curb', js: true do @@ -176,4 +181,3 @@ end end end -