mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-18 14:02:15 +00:00
Risk assessment form now validates power training status where required
This commit is contained in:
23
Pipfile.lock
generated
23
Pipfile.lock
generated
@@ -309,10 +309,11 @@
|
||||
},
|
||||
"django-hcaptcha": {
|
||||
"hashes": [
|
||||
"sha256:2b80197c07bb8444249bcce3758b0472d369cca309fb02d7abcd0a856431b76b"
|
||||
"sha256:18804fb38a01827b6c65d111bac31265c1b96fcf52d7a54c3e2d2cb1c62ddcde",
|
||||
"sha256:b2519eaf0cc97865ac72f825301122c5cf61e1e4852d6895994160222acb6c1a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.1.0"
|
||||
"version": "==0.2.0"
|
||||
},
|
||||
"django-htmlmin": {
|
||||
"hashes": [
|
||||
@@ -362,11 +363,11 @@
|
||||
},
|
||||
"django-widget-tweaks": {
|
||||
"hashes": [
|
||||
"sha256:19bcb66a4a9e68493ced04e7124882d753c5be517ed001556f9e35a40147f545",
|
||||
"sha256:d6c64fbf92cd2df9031f597c1374982233c05a1190d295c39d1c57ce007569c7"
|
||||
"sha256:01b911a1b47629de0a3a3097774798dee4eb703b94d41666929f688d5f77c723",
|
||||
"sha256:07674e32031eda81077f0b8e390ce78d1d415e700cedd0396ef0ce452e95b94d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.4.9"
|
||||
"version": "==1.4.11"
|
||||
},
|
||||
"envparse": {
|
||||
"hashes": [
|
||||
@@ -861,11 +862,11 @@
|
||||
},
|
||||
"sentry-sdk": {
|
||||
"hashes": [
|
||||
"sha256:2a1757d6611e4bec7d672c2b7ef45afef79fed201d064f53994753303944f5a8",
|
||||
"sha256:e4cb107e305b2c1b919414775fa73a9997f996447417d22b98e7610ded1e9eb5"
|
||||
"sha256:2cec50166bcb67e1965f8073541b2321e3864cd6fd42a526bcde9f0c4e4cc3f8",
|
||||
"sha256:7bbaa32bba806ec629962f207b597e86831c7ee2c1f287c21ba7de7fea9a9c46"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.5.1"
|
||||
"version": "==1.5.2"
|
||||
},
|
||||
"simplejson": {
|
||||
"hashes": [
|
||||
@@ -1538,11 +1539,11 @@
|
||||
},
|
||||
"pytest-reverse": {
|
||||
"hashes": [
|
||||
"sha256:9f2a3b163378922dd332ed056a58af4cfd1ccc8ad4a76606f43ed43cfff2140b",
|
||||
"sha256:d878e28c785fb20291580aa816d566a21beac508e06a2c9eb4f934d49c31ce5c"
|
||||
"sha256:1695b7c9e51b28db5af13d579b33b54a80958d86b886dfabd2a246bcad3e082e",
|
||||
"sha256:6acfb50acd11caf3d222366f5e1458dea2351d47b6ca5b08ab408158636250ba"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.0"
|
||||
"version": "==1.4.0"
|
||||
},
|
||||
"pytest-splinter": {
|
||||
"hashes": [
|
||||
|
||||
@@ -8,6 +8,7 @@ from django.utils import timezone
|
||||
from reversion import revisions as reversion
|
||||
|
||||
from RIGS import models
|
||||
from training.models import TrainingLevel
|
||||
|
||||
# Override the django form defaults to use the HTML date/time/datetime UI elements
|
||||
forms.DateField.widget = forms.DateInput(attrs={'type': 'date'})
|
||||
@@ -164,6 +165,9 @@ class EventRiskAssessmentForm(forms.ModelForm):
|
||||
], attrs={'class': 'custom-control-input', 'required': 'true'})
|
||||
|
||||
def clean(self):
|
||||
if self.cleaned_data.get('big_power'):
|
||||
if not self.cleaned_data.get('power_mic').level_qualifications.filter(level__department=TrainingLevel.POWER).exists():
|
||||
self.add_error('power_mic', forms.ValidationError("Your Power MIC must be a Power Technician.", code="power_tech_required"))
|
||||
# Check expected values
|
||||
unexpected_values = []
|
||||
for field, value in models.RiskAssessment.expected_values.items():
|
||||
|
||||
@@ -99,7 +99,7 @@ class RevisionMixin(object):
|
||||
version = self.current_version
|
||||
if version is None:
|
||||
return None
|
||||
return "V{0} | R{1}".format(version.pk, version.revision.pk)
|
||||
return f"V{version.pk} | R{version.revision.pk}"
|
||||
|
||||
|
||||
class Person(models.Model, RevisionMixin):
|
||||
@@ -207,7 +207,7 @@ class VatRate(models.Model, RevisionMixin):
|
||||
get_latest_by = 'start_at'
|
||||
|
||||
def __str__(self):
|
||||
return self.comment + " " + str(self.start_at) + " @ " + str(self.as_percent) + "%"
|
||||
return f"{self.comment} {self.start_at} @ {self.as_percent}%"
|
||||
|
||||
|
||||
class Venue(models.Model, RevisionMixin):
|
||||
@@ -347,10 +347,10 @@ class Event(models.Model, RevisionMixin):
|
||||
if self.pk:
|
||||
if self.is_rig:
|
||||
return str("N%05d" % self.pk)
|
||||
else:
|
||||
return self.pk
|
||||
else:
|
||||
return "????"
|
||||
|
||||
return self.pk
|
||||
|
||||
return "????"
|
||||
|
||||
# Calculated values
|
||||
"""
|
||||
@@ -475,7 +475,7 @@ class Event(models.Model, RevisionMixin):
|
||||
return reverse('event_detail', kwargs={'pk': self.pk})
|
||||
|
||||
def __str__(self):
|
||||
return "{}: {}".format(self.display_id, self.name)
|
||||
return f"{self.display_id}: {self.name}"
|
||||
|
||||
def clean(self):
|
||||
errdict = {}
|
||||
@@ -521,11 +521,11 @@ class EventItem(models.Model, RevisionMixin):
|
||||
ordering = ['order']
|
||||
|
||||
def __str__(self):
|
||||
return "{}.{}: {} | {}".format(self.event_id, self.order, self.event.name, self.name)
|
||||
return f"{self.event_id}.{self.order}: {self.event.name} | {self.name}"
|
||||
|
||||
@property
|
||||
def activity_feed_string(self):
|
||||
return str("item {}".format(self.name))
|
||||
return f"item {self.name}"
|
||||
|
||||
|
||||
@reversion.register
|
||||
@@ -543,7 +543,7 @@ class EventAuthorisation(models.Model, RevisionMixin):
|
||||
|
||||
@property
|
||||
def activity_feed_string(self):
|
||||
return "{} (requested by {})".format(self.event.display_id, self.sent_by.initials)
|
||||
return f"{self.event.display_id} (requested by {self.sent_by.initials})"
|
||||
|
||||
|
||||
class InvoiceManager(models.Manager):
|
||||
@@ -671,7 +671,6 @@ class RiskAssessment(models.Model, RevisionMixin):
|
||||
|
||||
# Power
|
||||
big_power = models.BooleanField(help_text="Does the event require larger power supplies than 13A or 16A single phase wall sockets, or draw more than 20A total current?")
|
||||
# If yes to the above two, you must answer...
|
||||
power_mic = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='power_mic', blank=True, null=True,
|
||||
verbose_name="Power MIC", on_delete=models.CASCADE, help_text="Who is the Power MIC? (if yes to the above question, this person <em>must</em> be a Power Technician or Power Supervisor)")
|
||||
outside = models.BooleanField(help_text="Is the event outdoors?")
|
||||
|
||||
@@ -2,9 +2,7 @@ from django.conf import settings
|
||||
import django
|
||||
import pytest
|
||||
from django.core.management import call_command
|
||||
from RIGS.models import VatRate, Profile
|
||||
import random
|
||||
from django.db import connection
|
||||
from RIGS.models import VatRate
|
||||
from PyRIGS.tests import pages
|
||||
import os
|
||||
from selenium import webdriver
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
from django import forms
|
||||
|
||||
from datetime import date
|
||||
|
||||
from training import models
|
||||
from RIGS.models import Profile
|
||||
|
||||
|
||||
class SessionLogForm(forms.Form):
|
||||
pass
|
||||
|
||||
|
||||
class QualificationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = models.TrainingItemQualification
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
from django.db import models
|
||||
|
||||
from RIGS.models import RevisionMixin, Profile
|
||||
from reversion import revisions as reversion
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
|
||||
from django.utils.safestring import SafeData, mark_safe
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
|
||||
@reversion.register(for_concrete_model=False, fields=[], follow=["qualifications_obtained", "level_qualifications"])
|
||||
@@ -105,13 +103,13 @@ class TrainingItemQualification(models.Model, RevisionMixin):
|
||||
return str("{} in {}".format(self.get_depth_display(), self.item))
|
||||
|
||||
@classmethod
|
||||
def get_colour_from_depth(obj, depth):
|
||||
def get_colour_from_depth(cls, obj, depth):
|
||||
if depth == 0:
|
||||
return "warning"
|
||||
elif depth == 1:
|
||||
if depth == 1:
|
||||
return "success"
|
||||
else:
|
||||
return "info"
|
||||
|
||||
return "info"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('trainee_item_detail', kwargs={'pk': self.trainee.pk})
|
||||
@@ -157,16 +155,16 @@ class TrainingLevel(models.Model, RevisionMixin):
|
||||
def department_colour(self):
|
||||
if self.department == self.SOUND:
|
||||
return "info"
|
||||
elif self.department == self.LIGHTING:
|
||||
if self.department == self.LIGHTING:
|
||||
return "dark"
|
||||
elif self.department == self.POWER:
|
||||
if self.department == self.POWER:
|
||||
return "danger"
|
||||
elif self.department == self.RIGGING:
|
||||
if self.department == self.RIGGING:
|
||||
return "warning"
|
||||
elif self.department == self.HAULAGE:
|
||||
if self.department == self.HAULAGE:
|
||||
return "light"
|
||||
else:
|
||||
return "primary"
|
||||
|
||||
return "primary"
|
||||
|
||||
def get_requirements_of_depth(self, depth):
|
||||
return self.requirements.filter(depth=depth)
|
||||
@@ -197,8 +195,8 @@ class TrainingLevel(models.Model, RevisionMixin):
|
||||
|
||||
if len(needed_qualifications) > 0:
|
||||
return int(relavant_qualifications / float(len(needed_qualifications)) * 100)
|
||||
else:
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
def user_has_requirements(self, user):
|
||||
has_required_items = all(TrainingItem.user_has_qualification(req.item, user, req.depth) for req in self.requirements.all())
|
||||
@@ -225,7 +223,7 @@ class TrainingLevel(models.Model, RevisionMixin):
|
||||
@property
|
||||
def get_icon(self):
|
||||
if self.icon is not None:
|
||||
icon = "<span class='fas fa-{}'></span>".format(self.icon)
|
||||
icon = f"<span class='fas fa-{self.icon}'></span>"
|
||||
else:
|
||||
icon = "".join([w[0] for w in str(self).split()])
|
||||
return mark_safe("<span class='badge badge-{} badge-pill' data-toggle='tooltip' title='{}'>{}</span>".format(self.department_colour, str(self), icon))
|
||||
@@ -260,14 +258,14 @@ class TrainingLevelQualification(models.Model, RevisionMixin):
|
||||
return self.level.get_icon
|
||||
|
||||
def clean(self):
|
||||
if level.level >= TrainingLevel.SUPERVISOR and level.department != TrainingLevel.HAULAGE:
|
||||
trainee.is_supervisor = True
|
||||
trainee.save()
|
||||
if self.level.level >= TrainingLevel.SUPERVISOR and self.level.department != TrainingLevel.HAULAGE:
|
||||
self.trainee.is_supervisor = True
|
||||
self.trainee.save()
|
||||
|
||||
def __str__(self):
|
||||
if self.level.is_common_competencies:
|
||||
return "{} is qualified in the {}".format(self.trainee, self.level)
|
||||
return "{} is qualified as a {}".format(self.trainee, self.level)
|
||||
return f"{self.trainee} is qualified in the {self.level}"
|
||||
return f"{self.trainee} is qualified as a {self.level}"
|
||||
|
||||
class Meta:
|
||||
unique_together = ["trainee", "level"]
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import reversion
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse_lazy
|
||||
from django.views import generic
|
||||
from PyRIGS.views import OEmbedView, is_ajax, ModalURLMixin
|
||||
from training import models, forms
|
||||
from django.utils import timezone
|
||||
from django.db import transaction
|
||||
from django.db.models import Q, Count, OuterRef, F, Subquery, Window
|
||||
from django.db.models import Q, Count
|
||||
|
||||
from PyRIGS.views import is_ajax, ModalURLMixin
|
||||
from training import models, forms
|
||||
from users import views
|
||||
|
||||
|
||||
@@ -98,12 +97,12 @@ class TraineeList(generic.ListView):
|
||||
def get_queryset(self):
|
||||
q = self.request.GET.get('q', "")
|
||||
|
||||
filter = Q(first_name__icontains=q) | Q(last_name__icontains=q) | Q(initials__icontains=q)
|
||||
fil = Q(first_name__icontains=q) | Q(last_name__icontains=q) | Q(initials__icontains=q)
|
||||
|
||||
# try and parse an int
|
||||
try:
|
||||
val = int(q)
|
||||
filter = filter | Q(pk=val)
|
||||
fil = fil | Q(pk=val)
|
||||
except: # noqa
|
||||
# not an integer
|
||||
pass
|
||||
@@ -200,7 +199,7 @@ class RemoveRequirement(generic.DeleteView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["page_title"] = "Delete Requirement '{}' from Training Level {}?".format(self.object, self.object.level)
|
||||
context["page_title"] = f"Delete Requirement '{self.object}' from Training Level {self.object.level}?"
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
|
||||
Reference in New Issue
Block a user