From 3cb0d82130b7b5451b04a44d91c3a3bc9a68c625 Mon Sep 17 00:00:00 2001 From: FreneticScribbler Date: Sat, 10 Oct 2020 12:14:29 +0100 Subject: [PATCH] Initial pass at soop-consult confirmation screen for RAs --- RIGS/forms.py | 13 ++++- RIGS/hs.py | 2 + ...042_riskassessment_supervisor_consulted.py | 18 +++++++ RIGS/models.py | 26 ++++++++-- RIGS/templates/risk_assessment_form.html | 34 ++++++++++--- RIGS/templatetags/filters.py | 6 +-- RIGS/tests/pages.py | 1 + RIGS/tests/test_interaction.py | 51 ++++++++++++------- 8 files changed, 120 insertions(+), 31 deletions(-) create mode 100644 RIGS/migrations/0042_riskassessment_supervisor_consulted.py diff --git a/RIGS/forms.py b/RIGS/forms.py index f3ac49d3..6faf6e67 100644 --- a/RIGS/forms.py +++ b/RIGS/forms.py @@ -161,12 +161,23 @@ class EventRiskAssessmentForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(EventRiskAssessmentForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): - if field.__class__ == forms.BooleanField: + if str(name) == 'supervisor_consulted': + field.widget = forms.CheckboxInput() + elif field.__class__ == forms.BooleanField: field.widget = forms.RadioSelect(choices=[ (True, 'Yes'), (False, 'No') ], attrs={'class': 'custom-control-input', 'required': 'true'}) + def clean(self): + unexpected_values = [] + for field, value in models.RiskAssessment.expected_values.items(): + if self.cleaned_data.get(field) != value: + unexpected_values.append("
  • {}
  • ".format(self._meta.model._meta.get_field(field).help_text)) + if len(unexpected_values) > 0 and not self.cleaned_data.get('supervisor_consulted'): + raise forms.ValidationError("Your answers to these questions: require consulting with a supervisor.".format(''.join([str(elem) for elem in unexpected_values])), code='unusual_answers') + return super(EventRiskAssessmentForm, self).clean() + class Meta: model = models.RiskAssessment fields = '__all__' diff --git a/RIGS/hs.py b/RIGS/hs.py index ad850c9b..188e1e46 100644 --- a/RIGS/hs.py +++ b/RIGS/hs.py @@ -36,6 +36,7 @@ class EventRiskAssessmentCreate(generic.CreateView): epk = self.kwargs.get('pk') event = models.Event.objects.get(pk=epk) context['event'] = event + context['page_title'] = 'Create Risk Assessment for Event {}'.format(event.display_id) return context def get_success_url(self): @@ -60,6 +61,7 @@ class EventRiskAssessmentEdit(generic.UpdateView): ra = models.RiskAssessment.objects.get(pk=rpk) context['event'] = ra.event context['edit'] = True + context['page_title'] = 'Edit Risk Assessment for Event {}'.format(ra.event.display_id) return context diff --git a/RIGS/migrations/0042_riskassessment_supervisor_consulted.py b/RIGS/migrations/0042_riskassessment_supervisor_consulted.py new file mode 100644 index 00000000..69cd0669 --- /dev/null +++ b/RIGS/migrations/0042_riskassessment_supervisor_consulted.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2020-10-10 10:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('RIGS', '0041_auto_20200929_1749'), + ] + + operations = [ + migrations.AddField( + model_name='riskassessment', + name='supervisor_consulted', + field=models.BooleanField(blank=True, null=True), + ), + ] diff --git a/RIGS/models.py b/RIGS/models.py index e054b4ff..458b9929 100644 --- a/RIGS/models.py +++ b/RIGS/models.py @@ -667,9 +667,29 @@ class RiskAssessment(models.Model, RevisionMixin): reviewed_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name="Reviewer", on_delete=models.CASCADE) - inverted_fields = ['nonstandard_equipment', 'nonstandard_use', 'contractors', 'other_companies', 'crew_fatigue', 'big_power', - 'generators', 'other_companies_power', 'nonstandard_equipment_power', 'multiple_electrical_environments', 'noise_monitoring' - 'special_structures', 'suspended_structures'] + supervisor_consulted = models.BooleanField(null=True) + + expected_values = { + 'nonstandard_equipment': False, + 'nonstandard_use': False, + 'contractors': False, + 'other_companies': False, + 'crew_fatigue': False, + 'big_power': False, + 'generators': False, + 'other_companies_power': False, + 'nonstandard_equipment_power': False, + 'multiple_electrical_environments': False, + 'noise_monitoring': False, + 'known_venue': True, + 'safe_loading': True, + 'safe_storage': True, + 'area_outside_of_control': False, + 'barrier_required': False, + 'nonstandard_emergency_procedure': False, + 'special_structures': False, + 'suspended_structures': False, + } class Meta: ordering = ['event'] diff --git a/RIGS/templates/risk_assessment_form.html b/RIGS/templates/risk_assessment_form.html index 5606834f..8a807ac4 100644 --- a/RIGS/templates/risk_assessment_form.html +++ b/RIGS/templates/risk_assessment_form.html @@ -2,8 +2,7 @@ {% load widget_tweaks %} {% load static %} {% load help_text from filters %} - -{% block title %}{% if edit %}Edit{% else %}Create{% endif %} Risk Assessment for Event N{{ event.pk|stringformat:"05d" }}{% endblock %} +{% load nice_errors from filters %} {% block css %} {{ block.super }} @@ -28,13 +27,34 @@ {% endblock %} {% block content %} -
    -

    {% if edit %}Edit{% else %}Create{% endif %} Risk Assessment for Event N{{ event.pk|stringformat:"05d" }}

    - {% include 'form_errors.html' %} +
    + {% if form.errors %} +
    + +
    + {% with form|nice_errors as qq %} + {% for error_name,desc in qq.items %} + {% if error_name == 'General form errors' %} + {{ form.non_field_errors.0|safe }} +
    + {% render_field form.supervisor_consulted class+="form-check-input" form="form" %}
    + +
    + {% else %} + +
    {{error_name}}
    +
    {{desc}}
    +
    + {% endif %} + {% endfor %} + {% endwith %} +
    +
    + {% endif %} {% if edit %} -
    + {% else %} - + {% endif %} diff --git a/RIGS/templatetags/filters.py b/RIGS/templatetags/filters.py index e36664ed..82a9f78b 100644 --- a/RIGS/templatetags/filters.py +++ b/RIGS/templatetags/filters.py @@ -34,8 +34,8 @@ def to_class_name(value): return value.__class__.__name__ -@register.filter -def nice_errors(form, non_field_msg='General form errors'): +@register.filter(needs_autoescape=True) +def nice_errors(form, non_field_msg='General form errors', autoescape=True): nice_errors = ErrorDict() if isinstance(form, forms.BaseForm): for field, errors in list(form.errors.items()): @@ -123,7 +123,7 @@ def orderby(request, field, attr): def get_field(obj, field, autoescape=True): value = getattr(obj, field) if(isinstance(value, bool)): - value = yesnoi(value, field in obj.inverted_fields) + value = yesnoi(value) elif(isinstance(value, str)): value = truncatewords(value, 20) return mark_safe(value) diff --git a/RIGS/tests/pages.py b/RIGS/tests/pages.py index 18450cf7..edfbdf60 100644 --- a/RIGS/tests/pages.py +++ b/RIGS/tests/pages.py @@ -206,6 +206,7 @@ class CreateRiskAssessment(FormPage): 'special_structures': (regions.RadioSelect, (By.ID, 'id_special_structures')), 'persons_responsible_structures': (regions.TextBox, (By.ID, 'id_persons_responsible_structures')), 'suspended_structures': (regions.RadioSelect, (By.ID, 'id_suspended_structures')), + 'supervisor_consulted': (regions.CheckBox, (By.ID, 'id_supervisor_consulted')), } @property diff --git a/RIGS/tests/test_interaction.py b/RIGS/tests/test_interaction.py index b19b76bb..4cbb8fd7 100644 --- a/RIGS/tests/test_interaction.py +++ b/RIGS/tests/test_interaction.py @@ -662,6 +662,30 @@ class TestHealthAndSafety(BaseRigboardTest): description="start future no end", purchase_order='TESTPO', person=self.client) + self.testEvent2 = models.Event.objects.create(name="TE E2", status=models.Event.PROVISIONAL, + start_date=date.today() + timedelta(days=6), + description="start future no end", + purchase_order='TESTPO', + person=self.client) + self.testRA = models.RiskAssessment.objects.create(event=self.testEvent2, supervisor_consulted=False, nonstandard_equipment=False, + nonstandard_use=False, + contractors=False, + other_companies=False, + crew_fatigue=False, + big_power=False, + generators=False, + other_companies_power=False, + nonstandard_equipment_power=False, + multiple_electrical_environments=False, + noise_monitoring=False, + known_venue=True, + safe_loading=True, + safe_storage=True, + area_outside_of_control=False, + barrier_required=False, + nonstandard_emergency_procedure=False, + special_structures=False, + suspended_structures=False) self.page = pages.EventDetail(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() # TODO Can I loop through all the boolean fields and test them at once? @@ -700,8 +724,12 @@ class TestHealthAndSafety(BaseRigboardTest): self.page.nonstandard_emergency_procedure = False self.page.special_structures = False self.page.persons_responsible_structures = "Nobody and her cat, She" - self.page.suspended_structures = False + self.page.suspended_structures = True + self.page.submit() + self.assertFalse(self.page.success) + + self.page.suspended_structures = False self.page.submit() self.assertTrue(self.page.success) @@ -710,27 +738,16 @@ class TestHealthAndSafety(BaseRigboardTest): self.assertIn('edit', self.driver.current_url) def test_ra_edit(self): - # Create assessment to edit - self.page = pages.CreateRiskAssessment(self.driver, self.live_server_url, event_id=self.testEvent.pk).open() - self.page.nonstandard_equipment = False - self.page.nonstandard_use = False - self.page.contractors = False - self.page.other_companies = False - self.page.crew_fatigue = False - self.page.general_notes = "There are no notes." - self.page.big_power = False - self.page.power_mic.search(self.profile.name) - self.page.power_mic.toggle() - self.assertFalse(self.page.power_mic.is_open) - self.page.remove_all_required() - self.page.submit() - self.page = pages.EditRiskAssessment(self.driver, self.live_server_url, pk=models.RiskAssessment.objects.get(event=self.testEvent.pk).pk).open() + self.page = pages.EditRiskAssessment(self.driver, self.live_server_url, pk=self.testRA.pk).open() self.page.nonstandard_equipment = nse = True self.page.general_notes = gn = "There are some notes, but I've not written them here as that would be helpful" self.page.submit() + self.assertFalse(self.page.success) + self.page.supervisor_consulted = True + self.page.submit() self.assertTrue(self.page.success) # Check that data is right - ra = models.RiskAssessment.objects.get(event=self.testEvent.pk) + ra = models.RiskAssessment.objects.get(pk=self.testRA.pk) self.assertEqual(ra.general_notes, gn) self.assertEqual(ra.nonstandard_equipment, nse)