diff --git a/RIGS/admin.py b/RIGS/admin.py
index a46a0eee..d7dbd72b 100644
--- a/RIGS/admin.py
+++ b/RIGS/admin.py
@@ -206,3 +206,8 @@ class RiskAssessmentAdmin(VersionAdmin):
@admin.register(models.EventChecklist)
class EventChecklistAdmin(VersionAdmin):
list_display = ('id', 'event', 'reviewed_at', 'reviewed_by')
+
+
+@admin.register(models.PowerTestRecord)
+class EventChecklistAdmin(VersionAdmin):
+ list_display = ('id', 'event', 'reviewed_at', 'reviewed_by')
diff --git a/RIGS/forms.py b/RIGS/forms.py
index 0664875d..78128678 100644
--- a/RIGS/forms.py
+++ b/RIGS/forms.py
@@ -283,3 +283,17 @@ class EventChecklistForm(forms.ModelForm):
model = models.EventChecklist
fields = '__all__'
exclude = ['reviewed_at', 'reviewed_by']
+
+
+class PowerTestRecordForm(forms.ModelForm):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ for name, field in self.fields.items():
+ if field.__class__ == forms.NullBooleanField:
+ # Only display yes/no to user, the 'none' is only ever set in the background
+ field.widget = forms.CheckboxInput()
+
+ class Meta:
+ model = models.PowerTestRecord
+ fields = '__all__'
+ exclude = ['reviewed_at', 'reviewed_by']
diff --git a/RIGS/migrations/0046_create_powertests.py b/RIGS/migrations/0046_create_powertests.py
new file mode 100644
index 00000000..95f1c8e4
--- /dev/null
+++ b/RIGS/migrations/0046_create_powertests.py
@@ -0,0 +1,71 @@
+# Generated by Django 3.2.16 on 2023-05-08 15:58
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import versioning.versioning
+
+def migrate_old_data(apps, schema_editor):
+ EventChecklist = apps.get_model('RIGS', 'EventChecklist')
+ PowerTestRecord = apps.get_model('RIGS', 'PowerTestRecord')
+ for ec in EventChecklist.objects.all():
+ # New highscore for the most pythonic BS I've ever written.
+ PowerTestRecord.objects.create(event=ec.event, **{i.name:getattr(ec, i.attname) for i in PowerTestRecord._meta.get_fields() if not (i.is_relation or i.auto_created)})
+
+
+def revert(apps, schema_editor):
+ apps.get_model('RIGS', 'PowerTestRecord').objects.all().delete()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('RIGS', '0045_alter_profile_is_approved'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='PowerTestRecord',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='power_tests', to='RIGS.event')),
+ ('notes', models.TextField(blank=True, default='')),
+ ('venue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='RIGS.venue')),
+ ('reviewed_at', models.DateTimeField(null=True)),
+ ('rcds', models.BooleanField(blank=True, help_text='RCDs installed where needed and tested?', null=True)),
+ ('supply_test', models.BooleanField(blank=True, help_text='Electrical supplies tested?
(using socket tester)', null=True)),
+ ('earthing', models.BooleanField(blank=True, help_text='Equipment appropriately earthed?
(truss, stage, generators etc)', null=True)),
+ ('pat', models.BooleanField(blank=True, help_text='All equipment in PAT period?', null=True)),
+ ('source_rcd', models.BooleanField(blank=True, help_text='Source RCD protected?
(if cable is more than 3m long) ', null=True)),
+ ('labelling', models.BooleanField(blank=True, help_text='Appropriate and clear labelling on distribution and cabling?', null=True)),
+ ('fd_voltage_l1', models.IntegerField(blank=True, help_text='L1 - N', null=True, verbose_name='First Distro Voltage L1-N')),
+ ('fd_voltage_l2', models.IntegerField(blank=True, help_text='L2 - N', null=True, verbose_name='First Distro Voltage L2-N')),
+ ('fd_voltage_l3', models.IntegerField(blank=True, help_text='L3 - N', null=True, verbose_name='First Distro Voltage L3-N')),
+ ('fd_phase_rotation', models.BooleanField(blank=True, help_text='Phase Rotation
(if required)', null=True, verbose_name='Phase Rotation')),
+ ('fd_earth_fault', models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS)', max_digits=5, null=True, verbose_name='Earth Fault Loop Impedance')),
+ ('fd_pssc', models.IntegerField(blank=True, help_text='Prospective Short Circuit Current', null=True, verbose_name='PSCC')),
+ ('w1_description', models.CharField(blank=True, default='', help_text='Description', max_length=255)),
+ ('w1_polarity', models.BooleanField(blank=True, help_text='Polarity Checked?', null=True)),
+ ('w1_voltage', models.IntegerField(blank=True, help_text='Voltage', null=True)),
+ ('w1_earth_fault', models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS)', max_digits=5, null=True, verbose_name='Earth Fault Loop Impedance')),
+ ('w2_description', models.CharField(blank=True, default='', help_text='Description', max_length=255)),
+ ('w2_polarity', models.BooleanField(blank=True, help_text='Polarity Checked?', null=True)),
+ ('w2_voltage', models.IntegerField(blank=True, help_text='Voltage', null=True)),
+ ('w2_earth_fault', models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS)', max_digits=5, null=True, verbose_name='Earth Fault Loop Impedance')),
+ ('w3_description', models.CharField(blank=True, default='', help_text='Description', max_length=255)),
+ ('w3_polarity', models.BooleanField(blank=True, help_text='Polarity Checked?', null=True)),
+ ('w3_voltage', models.IntegerField(blank=True, help_text='Voltage', null=True)),
+ ('w3_earth_fault', models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS)', max_digits=5, null=True, verbose_name='Earth Fault Loop Impedance')),
+ ('all_rcds_tested', models.BooleanField(blank=True, help_text='All circuit RCDs tested?
(using test button)', null=True)),
+ ('public_sockets_tested', models.BooleanField(blank=True, help_text='Public/Performer accessible circuits tested?
(using socket tester)', null=True)),
+ ('reviewed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Reviewer')),
+ ],
+ options={
+ 'abstract': False,
+ 'ordering': ['event'],
+ 'permissions': [('review_power', 'Can review Power Test Records')],
+ },
+ bases=(models.Model, versioning.versioning.RevisionMixin),
+ ),
+ migrations.RunPython(migrate_old_data, reverse_code=revert),
+ ]
diff --git a/RIGS/migrations/0047_auto_20230508_1946.py b/RIGS/migrations/0047_auto_20230508_1946.py
new file mode 100644
index 00000000..555798be
--- /dev/null
+++ b/RIGS/migrations/0047_auto_20230508_1946.py
@@ -0,0 +1,117 @@
+# Generated by Django 3.2.16 on 2023-05-08 18:46
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('RIGS', '0046_create_powertests'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='all_rcds_tested',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='earthing',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='fd_earth_fault',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='fd_phase_rotation',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='fd_pssc',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='fd_voltage_l1',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='fd_voltage_l2',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='fd_voltage_l3',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='labelling',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='pat',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='public_sockets_tested',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='rcds',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='source_rcd',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='supply_test',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w1_description',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w1_earth_fault',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w1_polarity',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w1_voltage',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w2_description',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w2_earth_fault',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w2_polarity',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w2_voltage',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w3_description',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w3_earth_fault',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w3_polarity',
+ ),
+ migrations.RemoveField(
+ model_name='eventchecklist',
+ name='w3_voltage',
+ ),
+ ]
diff --git a/RIGS/models.py b/RIGS/models.py
index 30fdecd8..0b7720ea 100644
--- a/RIGS/models.py
+++ b/RIGS/models.py
@@ -689,8 +689,21 @@ def validate_url(value):
raise ValidationError('URL must point to a location on the TEC Sharepoint')
+class ReviewableModel(models.Model):
+ reviewed_at = models.DateTimeField(null=True)
+ reviewed_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
+ verbose_name="Reviewer", on_delete=models.CASCADE)
+
+ @cached_property
+ def fieldz(self):
+ return [n.name for n in list(self._meta.get_fields()) if n.name != 'reviewed_at' and n.name != 'reviewed_by' and not n.is_relation and not n.auto_created]
+
+ class Meta:
+ abstract = True
+
+
@reversion.register
-class RiskAssessment(models.Model, RevisionMixin):
+class RiskAssessment(ReviewableModel, RevisionMixin):
SMALL = (0, 'Small')
MEDIUM = (1, 'Medium')
LARGE = (2, 'Large')
@@ -738,10 +751,6 @@ class RiskAssessment(models.Model, RevisionMixin):
# Blimey that was a lot of options
- reviewed_at = models.DateTimeField(null=True)
- reviewed_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
- verbose_name="Reviewer", on_delete=models.CASCADE)
-
supervisor_consulted = models.BooleanField(null=True)
expected_values = {
@@ -778,10 +787,6 @@ class RiskAssessment(models.Model, RevisionMixin):
('review_riskassessment', 'Can review Risk Assessments')
]
- @cached_property
- def fieldz(self):
- return [n.name for n in list(self._meta.get_fields()) if n.name != 'reviewed_at' and n.name != 'reviewed_by' and not n.is_relation and not n.auto_created]
-
@property
def event_size(self):
# Confirm event size. Check all except generators, since generators entails outside
@@ -811,7 +816,7 @@ class RiskAssessment(models.Model, RevisionMixin):
@reversion.register(follow=['vehicles', 'crew'])
-class EventChecklist(models.Model, RevisionMixin):
+class EventChecklist(ReviewableModel, RevisionMixin):
event = models.ForeignKey('Event', related_name='checklists', on_delete=models.CASCADE)
# General
@@ -830,6 +835,30 @@ class EventChecklist(models.Model, RevisionMixin):
hs_location = models.CharField(blank=True, default='', max_length=255, help_text="Location of Safety Bag/Box")
extinguishers_location = models.CharField(blank=True, default='', max_length=255, help_text="Location of fire extinguishers")
+ inverted_fields = []
+
+ class Meta:
+ ordering = ['event']
+ permissions = [
+ ('review_eventchecklist', 'Can review Event Checklists')
+ ]
+
+ @property
+ def activity_feed_string(self):
+ return str(self.event)
+
+ def get_absolute_url(self):
+ return reverse('ec_detail', kwargs={'pk': self.pk})
+
+ def __str__(self):
+ return f"{self.pk} - {self.event}"
+
+
+@reversion.register
+class PowerTestRecord(ReviewableModel, RevisionMixin):
+ event = models.ForeignKey('Event', related_name='power_tests', on_delete=models.CASCADE)
+ venue = models.ForeignKey('Venue', on_delete=models.CASCADE)
+ notes = models.TextField(blank=True, default='')
# Small Electrical Checks
rcds = models.BooleanField(blank=True, null=True, help_text="RCDs installed where needed and tested?")
supply_test = models.BooleanField(blank=True, null=True, help_text="Electrical supplies tested?
(using socket tester)")
@@ -865,32 +894,15 @@ class EventChecklist(models.Model, RevisionMixin):
all_rcds_tested = models.BooleanField(blank=True, null=True, help_text="All circuit RCDs tested?
(using test button)")
public_sockets_tested = models.BooleanField(blank=True, null=True, help_text="Public/Performer accessible circuits tested?
(using socket tester)")
- reviewed_at = models.DateTimeField(null=True)
- reviewed_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
- verbose_name="Reviewer", on_delete=models.CASCADE)
-
- inverted_fields = []
+ def __str__(self):
+ return f"{self.pk} - {self.event}"
class Meta:
ordering = ['event']
permissions = [
- ('review_eventchecklist', 'Can review Event Checklists')
+ ('review_power', 'Can review Power Test Records')
]
- @cached_property
- def fieldz(self):
- return [n.name for n in list(self._meta.get_fields()) if n.name != 'reviewed_at' and n.name != 'reviewed_by' and not n.is_relation and not n.auto_created]
-
- @property
- def activity_feed_string(self):
- return str(self.event)
-
- def get_absolute_url(self):
- return reverse('ec_detail', kwargs={'pk': self.pk})
-
- def __str__(self):
- return f"{self.pk} - {self.event}"
-
@reversion.register
class EventChecklistVehicle(models.Model, RevisionMixin):
diff --git a/RIGS/templates/hs/event_checklist_form.html b/RIGS/templates/hs/event_checklist_form.html
index 6db9f398..2db2899a 100644
--- a/RIGS/templates/hs/event_checklist_form.html
+++ b/RIGS/templates/hs/event_checklist_form.html
@@ -228,123 +228,6 @@
- {% if event.riskassessment.event_size == 0 %}
-
Tests at first distro
-| Test | -Value | -||
|---|---|---|---|
| Voltage (cube meter) |
- {{ form.fd_voltage_l1.help_text }} | -{{ form.fd_voltage_l2.help_text }} | -{{ form.fd_voltage_l3.help_text }} | -
| {% render_field form.fd_voltage_l1 class+="form-control" style="min-width: 5rem;" %} | -{% render_field form.fd_voltage_l2 class+="form-control" style="min-width: 5rem;" %} | -{% render_field form.fd_voltage_l3 class+="form-control" style="min-width: 5rem;" %} | -|
| {{form.fd_phase_rotation.help_text|safe}} | -{% include 'partials/checklist_checkbox.html' with formitem=form.fd_phase_rotation %} | -||
| {{form.fd_earth_fault.help_text|safe}} | -{% render_field form.fd_earth_fault class+="form-control" %} | -||
| {{form.fd_pssc.help_text|safe}} | -{% render_field form.fd_pssc class+="form-control" %} | -||
Tests at 'Worst Case' points (at least 1 point required)
-| Test | -Point 1 | -Point 2 | -Point 3 | -
|---|---|---|---|
| {{form.w1_description.help_text|safe}} | -{% render_field form.w1_description class+="form-control" style="min-width: 5rem;" %} | -{% render_field form.w2_description class+="form-control" style="min-width: 5rem;" %} | -{% render_field form.w3_description class+="form-control" style="min-width: 5rem;" %} | -
| {{form.w1_polarity.help_text|safe}} | -{% render_field form.w1_polarity %} | -{% render_field form.w2_polarity %} | -{% render_field form.w3_polarity %} | -
| {{form.w1_voltage.help_text|safe}} | -{% render_field form.w1_voltage class+="form-control" %} | -{% render_field form.w2_voltage class+="form-control" %} | -{% render_field form.w3_voltage class+="form-control" %} | -
| {{form.w1_earth_fault.help_text|safe}} | -{% render_field form.w1_earth_fault class+="form-control" %} | -{% render_field form.w2_earth_fault class+="form-control" %} | -{% render_field form.w3_earth_fault class+="form-control" %} | -
Tests at first distro
+| Test | +Value | +||
|---|---|---|---|
| Voltage (cube meter) |
+ {{ object|help_text:'fd_voltage_l1' }} | +{{ object|help_text:'fd_voltage_l2' }} | +{{ object|help_text:'fd_voltage_l3' }} | +
| {{ object.fd_voltage_l1 }} | +{{ object.fd_voltage_l2 }} | +{{ object.fd_voltage_l3 }} | +|
| {{ object|help_text:'fd_phase_rotation'|safe }} | +{{ object.fd_phase_rotation|yesnoi }} | +||
| {{ object|help_text:'fd_earth_fault'|safe}} | +{{ object.fd_earth_fault }} | +||
| {{ object|help_text:'fd_pssc'}} | +{{ object.fd_pssc }} | +||
Tests at 'Worst Case' points (at least 1 point required)
+| Test | +Point 1 | +Point 2 | +Point 3 | +
|---|---|---|---|
| {{ object|help_text:'w1_description'|safe}} | +{{ object.w1_description }} | +{{ object.w2_description|default:'' }} | +{{ object.w3_description|default:'' }} | +
| {{ object|help_text:'w1_polarity'|safe}} | +{{ object.w1_polarity|yesnoi }} | +{{ object.w2_polarity|default:''|yesnoi }} | +{{ object.w3_polarity|default:''|yesnoi }} | +
| {{ object|help_text:'w1_voltage'|safe}} | +{{ object.w1_voltage }} | +{{ object.w2_voltage|default:'' }} | +{{ object.w3_voltage|default:'' }} | +
| {{ object|help_text:'w1_earth_fault'|safe}} | +{{ object.w1_earth_fault }} | +{{ object.w2_earth_fault|default:'' }} | +{{ object.w3_earth_fault|default:'' }} | +