Make some improvements as suggested by DjangoDoctor

This commit is contained in:
2021-02-08 16:04:52 +00:00
parent e48e016cb9
commit a11e32252f
12 changed files with 372 additions and 109 deletions

View File

@@ -22,21 +22,12 @@ def create_datetime(year, month, day, hour, minute):
def create_browser(): def create_browser():
browser = env('BROWSER', default="chrome") options = webdriver.ChromeOptions()
if browser == "firefox": options.add_argument("--window-size=1920,1080")
options = webdriver.FirefoxOptions() options.add_argument("--headless")
options.headless = True if settings.CI:
driver = webdriver.Firefox(options=options) options.add_argument("--no-sandbox")
driver.set_window_position(0, 0) driver = webdriver.Chrome(options=options)
# Firefox is pissy about out of bounds otherwise
driver.set_window_size(3840, 2160)
else:
options = webdriver.ChromeOptions()
options.add_argument("--window-size=1920,1080")
options.add_argument("--headless")
if settings.CI:
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=options)
return driver return driver

View File

@@ -10,7 +10,7 @@ from django.http import Http404, HttpResponseRedirect
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.template.loader import get_template from django.template.loader import get_template
from django.urls import reverse_lazy from django.urls import reverse
from django.views import generic from django.views import generic
from z3c.rml import rml2pdf from z3c.rml import rml2pdf
@@ -92,8 +92,8 @@ class InvoiceVoid(generic.View):
object.save() object.save()
if object.void: if object.void:
return HttpResponseRedirect(reverse_lazy('invoice_list')) return HttpResponseRedirect(reverse('invoice_list'))
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': object.pk})) return HttpResponseRedirect(reverse('invoice_detail', kwargs={'pk': object.pk}))
class InvoiceDelete(generic.DeleteView): class InvoiceDelete(generic.DeleteView):
@@ -104,14 +104,14 @@ class InvoiceDelete(generic.DeleteView):
obj = self.get_object() obj = self.get_object()
if obj.payment_set.all().count() > 0: if obj.payment_set.all().count() > 0:
messages.info(self.request, 'To delete an invoice, delete the payments first.') messages.info(self.request, 'To delete an invoice, delete the payments first.')
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk})) return HttpResponseRedirect(reverse('invoice_detail', kwargs={'pk': obj.pk}))
return super(InvoiceDelete, self).get(pk) return super(InvoiceDelete, self).get(pk)
def post(self, request, pk): def post(self, request, pk):
obj = self.get_object() obj = self.get_object()
if obj.payment_set.all().count() > 0: if obj.payment_set.all().count() > 0:
messages.info(self.request, 'To delete an invoice, delete the payments first.') messages.info(self.request, 'To delete an invoice, delete the payments first.')
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk})) return HttpResponseRedirect(reverse('invoice_detail', kwargs={'pk': obj.pk}))
return super(InvoiceDelete, self).post(pk) return super(InvoiceDelete, self).post(pk)
def get_success_url(self): def get_success_url(self):
@@ -210,7 +210,7 @@ class InvoiceEvent(generic.View):
invoice.save() invoice.save()
messages.warning(self.request, 'Invoice voided') messages.warning(self.request, 'Invoice voided')
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': invoice.pk})) return HttpResponseRedirect(reverse('invoice_detail', kwargs={'pk': invoice.pk}))
class PaymentCreate(generic.CreateView): class PaymentCreate(generic.CreateView):
@@ -236,7 +236,7 @@ class PaymentCreate(generic.CreateView):
def get_success_url(self): def get_success_url(self):
messages.info(self.request, "location.reload()") messages.info(self.request, "location.reload()")
return reverse_lazy('closemodal') return reverse('closemodal')
class PaymentDelete(generic.DeleteView): class PaymentDelete(generic.DeleteView):

View File

@@ -15,5 +15,5 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.RunPython(approve_legacy) migrations.RunPython(approve_legacy, migrations.RunPython.noop)
] ]

View File

@@ -0,0 +1,199 @@
# Generated by Django 3.1.5 on 2021-02-08 16:03
import RIGS.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('RIGS', '0040_profile_dark_theme'),
]
operations = [
migrations.AlterField(
model_name='event',
name='auth_request_to',
field=models.EmailField(blank=True, default='', max_length=254),
),
migrations.AlterField(
model_name='event',
name='collector',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='collected by'),
),
migrations.AlterField(
model_name='event',
name='description',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='event',
name='meet_info',
field=models.CharField(blank=True, default='', max_length=255),
),
migrations.AlterField(
model_name='event',
name='notes',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='event',
name='payment_method',
field=models.CharField(blank=True, default='', max_length=255),
),
migrations.AlterField(
model_name='event',
name='payment_received',
field=models.CharField(blank=True, default='', max_length=255),
),
migrations.AlterField(
model_name='event',
name='purchase_order',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='PO'),
),
migrations.AlterField(
model_name='eventauthorisation',
name='account_code',
field=models.CharField(blank=True, default='', max_length=50),
),
migrations.AlterField(
model_name='eventauthorisation',
name='uni_id',
field=models.CharField(blank=True, default='', max_length=10, verbose_name='University ID'),
),
migrations.AlterField(
model_name='eventchecklist',
name='extinguishers_location',
field=models.CharField(blank=True, default='', help_text='Location of fire extinguishers', max_length=255),
),
migrations.AlterField(
model_name='eventchecklist',
name='hs_location',
field=models.CharField(blank=True, default='', help_text='Location of Safety Bag/Box', max_length=255),
),
migrations.AlterField(
model_name='eventchecklist',
name='w1_description',
field=models.CharField(blank=True, default='', help_text='Description', max_length=255),
),
migrations.AlterField(
model_name='eventchecklist',
name='w2_description',
field=models.CharField(blank=True, default='', help_text='Description', max_length=255),
),
migrations.AlterField(
model_name='eventchecklist',
name='w3_description',
field=models.CharField(blank=True, default='', help_text='Description', max_length=255),
),
migrations.AlterField(
model_name='eventitem',
name='description',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='organisation',
name='address',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='organisation',
name='email',
field=models.EmailField(blank=True, default='', max_length=254),
),
migrations.AlterField(
model_name='organisation',
name='notes',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='organisation',
name='phone',
field=models.CharField(blank=True, default='', max_length=15),
),
migrations.AlterField(
model_name='payment',
name='method',
field=models.CharField(blank=True, choices=[('C', 'Cash'), ('I', 'Internal'), ('E', 'External'), ('SU', 'SU Core'), ('T', 'TEC Adjustment')], default='', max_length=2),
),
migrations.AlterField(
model_name='person',
name='address',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='person',
name='email',
field=models.EmailField(blank=True, default='', max_length=254),
),
migrations.AlterField(
model_name='person',
name='notes',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='person',
name='phone',
field=models.CharField(blank=True, default='', max_length=15),
),
migrations.AlterField(
model_name='profile',
name='api_key',
field=models.CharField(blank=True, default='', editable=False, max_length=40),
),
migrations.AlterField(
model_name='profile',
name='phone',
field=models.CharField(default='', max_length=13, null=True),
),
migrations.AlterField(
model_name='riskassessment',
name='general_notes',
field=models.TextField(blank=True, default='', help_text='Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?'),
),
migrations.AlterField(
model_name='riskassessment',
name='persons_responsible_structures',
field=models.TextField(blank=True, default='', help_text='Who are the persons on site responsible for their use?'),
),
migrations.AlterField(
model_name='riskassessment',
name='power_notes',
field=models.TextField(blank=True, default='', help_text='Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?'),
),
migrations.AlterField(
model_name='riskassessment',
name='power_plan',
field=models.URLField(blank=True, default='', help_text="Upload your power plan to the <a href='https://nottinghamtec.sharepoint.com/'>Sharepoint</a> and submit a link", validators=[RIGS.models.validate_url]),
),
migrations.AlterField(
model_name='riskassessment',
name='rigging_plan',
field=models.URLField(blank=True, default='', help_text="Upload your rigging plan to the <a href='https://nottinghamtec.sharepoint.com/'>Sharepoint</a> and submit a link", validators=[RIGS.models.validate_url]),
),
migrations.AlterField(
model_name='riskassessment',
name='sound_notes',
field=models.TextField(blank=True, default='', help_text='Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?'),
),
migrations.AlterField(
model_name='venue',
name='address',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='venue',
name='email',
field=models.EmailField(blank=True, default='', max_length=254),
),
migrations.AlterField(
model_name='venue',
name='notes',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='venue',
name='phone',
field=models.CharField(blank=True, default='', max_length=15),
),
]

View File

@@ -12,7 +12,7 @@ from django.conf import settings
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.urls import reverse_lazy from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.functional import cached_property from django.utils.functional import cached_property
from reversion import revisions as reversion from reversion import revisions as reversion
@@ -21,11 +21,11 @@ from reversion.models import Version
class Profile(AbstractUser): class Profile(AbstractUser):
initials = models.CharField(max_length=5, unique=True, null=True, blank=False) initials = models.CharField(max_length=5, unique=True, null=True, blank=False)
phone = models.CharField(max_length=13, null=True, blank=True) phone = models.CharField(max_length=13, null=True, default='')
api_key = models.CharField(max_length=40, blank=True, editable=False, null=True) api_key = models.CharField(max_length=40, blank=True, editable=False, default='')
is_approved = models.BooleanField(default=False) is_approved = models.BooleanField(default=False)
last_emailed = models.DateTimeField(blank=True, # Currently only populated by the admin approval email. TODO: Populate it each time we send any email, might need that...
null=True) # Currently only populated by the admin approval email. TODO: Populate it each time we send any email, might need that... last_emailed = models.DateTimeField(blank=True, null=True)
dark_theme = models.BooleanField(default=False) dark_theme = models.BooleanField(default=False)
@classmethod @classmethod
@@ -103,12 +103,12 @@ class RevisionMixin(object):
class Person(models.Model, RevisionMixin): class Person(models.Model, RevisionMixin):
name = models.CharField(max_length=50) name = models.CharField(max_length=50)
phone = models.CharField(max_length=15, blank=True, null=True) phone = models.CharField(max_length=15, blank=True, default='')
email = models.EmailField(blank=True, null=True) email = models.EmailField(blank=True, default='')
address = models.TextField(blank=True, null=True) address = models.TextField(blank=True, default='')
notes = models.TextField(blank=True, null=True) notes = models.TextField(blank=True, default='')
def __str__(self): def __str__(self):
string = self.name string = self.name
@@ -134,17 +134,17 @@ class Person(models.Model, RevisionMixin):
return self.event_set.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic') return self.event_set.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic')
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('person_detail', kwargs={'pk': self.pk}) return reverse('person_detail', kwargs={'pk': self.pk})
class Organisation(models.Model, RevisionMixin): class Organisation(models.Model, RevisionMixin):
name = models.CharField(max_length=50) name = models.CharField(max_length=50)
phone = models.CharField(max_length=15, blank=True, null=True) phone = models.CharField(max_length=15, blank=True, default='')
email = models.EmailField(blank=True, null=True) email = models.EmailField(blank=True, default='')
address = models.TextField(blank=True, null=True) address = models.TextField(blank=True, default='')
notes = models.TextField(blank=True, null=True) notes = models.TextField(blank=True, default='')
union_account = models.BooleanField(default=False) union_account = models.BooleanField(default=False)
def __str__(self): def __str__(self):
@@ -171,7 +171,7 @@ class Organisation(models.Model, RevisionMixin):
return self.event_set.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic') return self.event_set.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic')
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('organisation_detail', kwargs={'pk': self.pk}) return reverse('organisation_detail', kwargs={'pk': self.pk})
class VatManager(models.Manager): class VatManager(models.Manager):
@@ -211,12 +211,12 @@ class VatRate(models.Model, RevisionMixin):
class Venue(models.Model, RevisionMixin): class Venue(models.Model, RevisionMixin):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
phone = models.CharField(max_length=15, blank=True, null=True) phone = models.CharField(max_length=15, blank=True, default='')
email = models.EmailField(blank=True, null=True) email = models.EmailField(blank=True, default='')
three_phase_available = models.BooleanField(default=False) three_phase_available = models.BooleanField(default=False)
notes = models.TextField(blank=True, null=True) notes = models.TextField(blank=True, default='')
address = models.TextField(blank=True, null=True) address = models.TextField(blank=True, default='')
def __str__(self): def __str__(self):
string = self.name string = self.name
@@ -229,7 +229,7 @@ class Venue(models.Model, RevisionMixin):
return self.event_set.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic') return self.event_set.order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic')
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('venue_detail', kwargs={'pk': self.pk}) return reverse('venue_detail', kwargs={'pk': self.pk})
class EventManager(models.Manager): class EventManager(models.Manager):
@@ -298,8 +298,8 @@ class Event(models.Model, RevisionMixin):
person = models.ForeignKey('Person', null=True, blank=True, on_delete=models.CASCADE) person = models.ForeignKey('Person', null=True, blank=True, on_delete=models.CASCADE)
organisation = models.ForeignKey('Organisation', blank=True, null=True, on_delete=models.CASCADE) organisation = models.ForeignKey('Organisation', blank=True, null=True, on_delete=models.CASCADE)
venue = models.ForeignKey('Venue', blank=True, null=True, on_delete=models.CASCADE) venue = models.ForeignKey('Venue', blank=True, null=True, on_delete=models.CASCADE)
description = models.TextField(blank=True, null=True) description = models.TextField(blank=True, default='')
notes = models.TextField(blank=True, null=True) notes = models.TextField(blank=True, default='')
status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL) status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL)
dry_hire = models.BooleanField(default=False) dry_hire = models.BooleanField(default=False)
is_rig = models.BooleanField(default=True) is_rig = models.BooleanField(default=True)
@@ -313,7 +313,7 @@ class Event(models.Model, RevisionMixin):
end_time = models.TimeField(blank=True, null=True) end_time = models.TimeField(blank=True, null=True)
access_at = models.DateTimeField(blank=True, null=True) access_at = models.DateTimeField(blank=True, null=True)
meet_at = models.DateTimeField(blank=True, null=True) meet_at = models.DateTimeField(blank=True, null=True)
meet_info = models.CharField(max_length=255, blank=True, null=True) meet_info = models.CharField(max_length=255, blank=True, default='')
# Crew management # Crew management
checked_in_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, null=True, checked_in_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, null=True,
@@ -322,15 +322,15 @@ class Event(models.Model, RevisionMixin):
verbose_name="MIC", on_delete=models.CASCADE) verbose_name="MIC", on_delete=models.CASCADE)
# Monies # Monies
payment_method = models.CharField(max_length=255, blank=True, null=True) payment_method = models.CharField(max_length=255, blank=True, default='')
payment_received = models.CharField(max_length=255, blank=True, null=True) payment_received = models.CharField(max_length=255, blank=True, default='')
purchase_order = models.CharField(max_length=255, blank=True, null=True, verbose_name='PO') purchase_order = models.CharField(max_length=255, blank=True, default='', verbose_name='PO')
collector = models.CharField(max_length=255, blank=True, null=True, verbose_name='collected by') collector = models.CharField(max_length=255, blank=True, default='', verbose_name='collected by')
# Authorisation request details # Authorisation request details
auth_request_by = models.ForeignKey('Profile', null=True, blank=True, on_delete=models.CASCADE) auth_request_by = models.ForeignKey('Profile', null=True, blank=True, on_delete=models.CASCADE)
auth_request_at = models.DateTimeField(null=True, blank=True) auth_request_at = models.DateTimeField(null=True, blank=True)
auth_request_to = models.EmailField(null=True, blank=True) auth_request_to = models.EmailField(blank=True, default='')
@property @property
def display_id(self): def display_id(self):
@@ -456,7 +456,7 @@ class Event(models.Model, RevisionMixin):
objects = EventManager() objects = EventManager()
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('event_detail', kwargs={'pk': self.pk}) return reverse('event_detail', kwargs={'pk': self.pk})
def __str__(self): def __str__(self):
return "{}: {}".format(self.display_id, self.name) return "{}: {}".format(self.display_id, self.name)
@@ -490,7 +490,7 @@ class Event(models.Model, RevisionMixin):
class EventItem(models.Model, RevisionMixin): class EventItem(models.Model, RevisionMixin):
event = models.ForeignKey('Event', related_name='items', blank=True, on_delete=models.CASCADE) event = models.ForeignKey('Event', related_name='items', blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True) description = models.TextField(blank=True, default='')
quantity = models.IntegerField() quantity = models.IntegerField()
cost = models.DecimalField(max_digits=10, decimal_places=2) cost = models.DecimalField(max_digits=10, decimal_places=2)
order = models.IntegerField() order = models.IntegerField()
@@ -505,7 +505,7 @@ class EventItem(models.Model, RevisionMixin):
ordering = ['order'] ordering = ['order']
def __str__(self): def __str__(self):
return str(self.event.pk) + "." + str(self.order) + ": " + self.event.name + " | " + self.name return "{}.{}: {} | {}".format(self.event_id, self.order, self.event.name, self.name)
@property @property
def activity_feed_string(self): def activity_feed_string(self):
@@ -517,13 +517,13 @@ class EventAuthorisation(models.Model, RevisionMixin):
event = models.OneToOneField('Event', related_name='authorisation', on_delete=models.CASCADE) event = models.OneToOneField('Event', related_name='authorisation', on_delete=models.CASCADE)
email = models.EmailField() email = models.EmailField()
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
uni_id = models.CharField(max_length=10, blank=True, null=True, verbose_name="University ID") uni_id = models.CharField(max_length=10, blank=True, default='', verbose_name="University ID")
account_code = models.CharField(max_length=50, blank=True, null=True) account_code = models.CharField(max_length=50, default='', blank=True)
amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="authorisation amount") amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="authorisation amount")
sent_by = models.ForeignKey('Profile', on_delete=models.CASCADE) sent_by = models.ForeignKey('Profile', on_delete=models.CASCADE)
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('event_detail', kwargs={'pk': self.event.pk}) return reverse('event_detail', kwargs={'pk': self.event_id})
@property @property
def activity_feed_string(self): def activity_feed_string(self):
@@ -562,11 +562,11 @@ class Invoice(models.Model, RevisionMixin):
return self.balance == 0 or self.void return self.balance == 0 or self.void
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('invoice_detail', kwargs={'pk': self.pk}) return reverse('invoice_detail', kwargs={'pk': self.pk})
@property @property
def activity_feed_string(self): def activity_feed_string(self):
return "#{} for Event {}".format(self.display_id, "N%05d" % self.event.pk) return "#{} for Event {}".format(self.display_id, self.event.display_id)
def __str__(self): def __str__(self):
return "%i: %s (%.2f)" % (self.pk, self.event, self.balance) return "%i: %s (%.2f)" % (self.pk, self.event, self.balance)
@@ -597,7 +597,7 @@ class Payment(models.Model, RevisionMixin):
invoice = models.ForeignKey('Invoice', on_delete=models.CASCADE) invoice = models.ForeignKey('Invoice', on_delete=models.CASCADE)
date = models.DateField() date = models.DateField()
amount = models.DecimalField(max_digits=10, decimal_places=2, help_text='Please use ex. VAT') amount = models.DecimalField(max_digits=10, decimal_places=2, help_text='Please use ex. VAT')
method = models.CharField(max_length=2, choices=METHODS, null=True, blank=True) method = models.CharField(max_length=2, choices=METHODS, default='', blank=True)
reversion_hide = True reversion_hide = True
@@ -632,10 +632,9 @@ class RiskAssessment(models.Model, RevisionMixin):
contractors = models.BooleanField(help_text="Are you using any external contractors?<br><small>i.e. Freelancers/Crewing Companies</small>") contractors = models.BooleanField(help_text="Are you using any external contractors?<br><small>i.e. Freelancers/Crewing Companies</small>")
other_companies = models.BooleanField(help_text="Are TEC working with any other companies on site?<br><small>e.g. TEC is providing the lighting while another company does sound</small>") other_companies = models.BooleanField(help_text="Are TEC working with any other companies on site?<br><small>e.g. TEC is providing the lighting while another company does sound</small>")
crew_fatigue = models.BooleanField(help_text="Is crew fatigue likely to be a risk at any point during this event?") crew_fatigue = models.BooleanField(help_text="Is crew fatigue likely to be a risk at any point during this event?")
general_notes = models.TextField(blank=True, null=True, help_text="Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?") general_notes = models.TextField(blank=True, default='', help_text="Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?")
# Power # Power
# event_size = models.IntegerField(blank=True, null=True, choices=SIZES)
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?") 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... # 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, power_mic = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='power_mic', blank=True, null=True,
@@ -645,12 +644,12 @@ class RiskAssessment(models.Model, RevisionMixin):
other_companies_power = models.BooleanField(help_text="Will TEC be supplying power to any other companies?") other_companies_power = models.BooleanField(help_text="Will TEC be supplying power to any other companies?")
nonstandard_equipment_power = models.BooleanField(help_text="Does the power plan require the use of any power equipment (distros, dimmers, motor controllers, etc.) that does not belong to TEC?") nonstandard_equipment_power = models.BooleanField(help_text="Does the power plan require the use of any power equipment (distros, dimmers, motor controllers, etc.) that does not belong to TEC?")
multiple_electrical_environments = models.BooleanField(help_text="Will the electrical installation occupy more than one electrical environment?") multiple_electrical_environments = models.BooleanField(help_text="Will the electrical installation occupy more than one electrical environment?")
power_notes = models.TextField(blank=True, null=True, help_text="Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?") power_notes = models.TextField(blank=True, default='', help_text="Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?")
power_plan = models.URLField(blank=True, null=True, help_text="Upload your power plan to the <a href='https://nottinghamtec.sharepoint.com/'>Sharepoint</a> and submit a link", validators=[validate_url]) power_plan = models.URLField(blank=True, default='', help_text="Upload your power plan to the <a href='https://nottinghamtec.sharepoint.com/'>Sharepoint</a> and submit a link", validators=[validate_url])
# Sound # Sound
noise_monitoring = models.BooleanField(help_text="Does the event require noise monitoring or any non-standard procedures in order to comply with health and safety legislation or site rules?") noise_monitoring = models.BooleanField(help_text="Does the event require noise monitoring or any non-standard procedures in order to comply with health and safety legislation or site rules?")
sound_notes = models.TextField(blank=True, null=True, help_text="Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?") sound_notes = models.TextField(blank=True, default='', help_text="Did you have to consult a supervisor about any of the above? If so who did you consult and what was the outcome?")
# Site # Site
known_venue = models.BooleanField(help_text="Is this venue new to you (the MIC) or new to TEC?") known_venue = models.BooleanField(help_text="Is this venue new to you (the MIC) or new to TEC?")
@@ -663,8 +662,8 @@ class RiskAssessment(models.Model, RevisionMixin):
# Structures # Structures
special_structures = models.BooleanField(help_text="Does the event require use of winch stands, motors, MPT Towers, or staging?") special_structures = models.BooleanField(help_text="Does the event require use of winch stands, motors, MPT Towers, or staging?")
suspended_structures = models.BooleanField(help_text="Are any structures (excluding projector screens and IWBs) being suspended from TEC's structures?") suspended_structures = models.BooleanField(help_text="Are any structures (excluding projector screens and IWBs) being suspended from TEC's structures?")
persons_responsible_structures = models.TextField(blank=True, null=True, help_text="Who are the persons on site responsible for their use?") persons_responsible_structures = models.TextField(blank=True, default='', help_text="Who are the persons on site responsible for their use?")
rigging_plan = models.URLField(blank=True, null=True, help_text="Upload your rigging plan to the <a href='https://nottinghamtec.sharepoint.com/'>Sharepoint</a> and submit a link", validators=[validate_url]) rigging_plan = models.URLField(blank=True, default='', help_text="Upload your rigging plan to the <a href='https://nottinghamtec.sharepoint.com/'>Sharepoint</a> and submit a link", validators=[validate_url])
# Blimey that was a lot of options # Blimey that was a lot of options
@@ -723,7 +722,7 @@ class RiskAssessment(models.Model, RevisionMixin):
return str(self.event) return str(self.event)
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('ra_detail', kwargs={'pk': self.pk}) return reverse('ra_detail', kwargs={'pk': self.pk})
def __str__(self): def __str__(self):
return "%i - %s" % (self.pk, self.event) return "%i - %s" % (self.pk, self.event)
@@ -746,8 +745,8 @@ class EventChecklist(models.Model, RevisionMixin):
trip_hazard = models.BooleanField(blank=True, null=True, help_text="Appropriate barriers around kit and cabling secured?") trip_hazard = models.BooleanField(blank=True, null=True, help_text="Appropriate barriers around kit and cabling secured?")
warning_signs = models.BooleanField(blank=True, help_text="Warning signs in place?<br><small>(strobe, smoke, power etc.)</small>") warning_signs = models.BooleanField(blank=True, help_text="Warning signs in place?<br><small>(strobe, smoke, power etc.)</small>")
ear_plugs = models.BooleanField(blank=True, null=True, help_text="Ear plugs issued to crew where needed?") ear_plugs = models.BooleanField(blank=True, null=True, help_text="Ear plugs issued to crew where needed?")
hs_location = models.CharField(blank=True, null=True, max_length=255, help_text="Location of Safety Bag/Box") hs_location = models.CharField(blank=True, default='', max_length=255, help_text="Location of Safety Bag/Box")
extinguishers_location = models.CharField(blank=True, null=True, max_length=255, help_text="Location of fire extinguishers") extinguishers_location = models.CharField(blank=True, default='', max_length=255, help_text="Location of fire extinguishers")
# Small Electrical Checks # Small Electrical Checks
rcds = models.BooleanField(blank=True, null=True, help_text="RCDs installed where needed and tested?") rcds = models.BooleanField(blank=True, null=True, help_text="RCDs installed where needed and tested?")
@@ -768,15 +767,15 @@ class EventChecklist(models.Model, RevisionMixin):
fd_earth_fault = models.IntegerField(blank=True, null=True, verbose_name="Earth Fault Loop Impedance", help_text="Earth Fault Loop Impedance (Z<small>S</small>)") fd_earth_fault = models.IntegerField(blank=True, null=True, verbose_name="Earth Fault Loop Impedance", help_text="Earth Fault Loop Impedance (Z<small>S</small>)")
fd_pssc = models.IntegerField(blank=True, null=True, verbose_name="PSCC", help_text="Prospective Short Circuit Current") fd_pssc = models.IntegerField(blank=True, null=True, verbose_name="PSCC", help_text="Prospective Short Circuit Current")
# Worst case points # Worst case points
w1_description = models.CharField(blank=True, null=True, max_length=255, help_text="Description") w1_description = models.CharField(blank=True, default='', max_length=255, help_text="Description")
w1_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?") w1_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?")
w1_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage") w1_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage")
w1_earth_fault = models.IntegerField(blank=True, null=True, help_text="Earth Fault Loop Impedance (Z<small>S</small>)") w1_earth_fault = models.IntegerField(blank=True, null=True, help_text="Earth Fault Loop Impedance (Z<small>S</small>)")
w2_description = models.CharField(blank=True, null=True, max_length=255, help_text="Description") w2_description = models.CharField(blank=True, default='', max_length=255, help_text="Description")
w2_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?") w2_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?")
w2_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage") w2_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage")
w2_earth_fault = models.IntegerField(blank=True, null=True, help_text="Earth Fault Loop Impedance (Z<small>S</small>)") w2_earth_fault = models.IntegerField(blank=True, null=True, help_text="Earth Fault Loop Impedance (Z<small>S</small>)")
w3_description = models.CharField(blank=True, null=True, max_length=255, help_text="Description") w3_description = models.CharField(blank=True, default='', max_length=255, help_text="Description")
w3_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?") w3_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?")
w3_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage") w3_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage")
w3_earth_fault = models.IntegerField(blank=True, null=True, help_text="Earth Fault Loop Impedance (Z<small>S</small>)") w3_earth_fault = models.IntegerField(blank=True, null=True, help_text="Earth Fault Loop Impedance (Z<small>S</small>)")
@@ -801,7 +800,7 @@ class EventChecklist(models.Model, RevisionMixin):
return str(self.event) return str(self.event)
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('ec_detail', kwargs={'pk': self.pk}) return reverse('ec_detail', kwargs={'pk': self.pk})
def __str__(self): def __str__(self):
return "%i - %s" % (self.pk, self.event) return "%i - %s" % (self.pk, self.event)

View File

@@ -153,7 +153,7 @@ class EventDuplicate(EventUpdate):
new.checked_in_by = None new.checked_in_by = None
# Remove all the authorisation information from the new event # Remove all the authorisation information from the new event
new.auth_request_to = None new.auth_request_to = ''
new.auth_request_by = None new.auth_request_by = None
new.auth_request_at = None new.auth_request_at = None

View File

@@ -4,7 +4,7 @@ from django.forms.forms import NON_FIELD_ERRORS
from django.forms.utils import ErrorDict from django.forms.utils import ErrorDict
from django.template.defaultfilters import stringfilter from django.template.defaultfilters import stringfilter
from django.template.defaultfilters import yesno, title, truncatewords from django.template.defaultfilters import yesno, title, truncatewords
from django.urls import reverse_lazy from django.urls import reverse
from django.utils.html import escape from django.utils.html import escape
from django.utils.safestring import SafeData, mark_safe from django.utils.safestring import SafeData, mark_safe
from django.utils.text import normalize_newlines from django.utils.text import normalize_newlines
@@ -173,7 +173,7 @@ def title_spaced(string):
@register.filter(needs_autoescape=True) @register.filter(needs_autoescape=True)
def namewithnotes(obj, url, autoescape=True): def namewithnotes(obj, url, autoescape=True):
if hasattr(obj, 'notes') and obj.notes is not None and len(obj.notes) > 0: if hasattr(obj, 'notes') and obj.notes is not None and len(obj.notes) > 0:
return mark_safe(obj.name + " <a href='{}'><span class='far fa-sticky-note'></span></a>".format(reverse_lazy(url, kwargs={'pk': obj.pk}))) return mark_safe(obj.name + " <a href='{}'><span class='far fa-sticky-note'></span></a>".format(reverse(url, kwargs={'pk': obj.pk})))
else: else:
return obj.name return obj.name

View File

@@ -311,7 +311,7 @@ class TestEventDuplicate(BaseRigboardTest):
# TODO Rewrite when EventDetail page is implemented # TODO Rewrite when EventDetail page is implemented
newEvent = models.Event.objects.latest('pk') newEvent = models.Event.objects.latest('pk')
self.assertEqual(newEvent.auth_request_to, None) assert newEvent.auth_request_to == ''
self.assertEqual(newEvent.auth_request_by, None) self.assertEqual(newEvent.auth_request_by, None)
self.assertEqual(newEvent.auth_request_at, None) self.assertEqual(newEvent.auth_request_at, None)
@@ -449,7 +449,7 @@ class TestEventDetail(BaseRigboardTest):
self.assertIn("N%05d | %s" % (self.testEvent.pk, self.testEvent.name), self.page.event_name) self.assertIn("N%05d | %s" % (self.testEvent.pk, self.testEvent.name), self.page.event_name)
self.assertEqual(self.client.name, self.page.name) self.assertEqual(self.client.name, self.page.name)
self.assertEqual(self.client.email, self.page.email) self.assertEqual(self.client.email, self.page.email)
self.assertEqual(self.client.phone, None) assert self.client.phone == ''
@screenshot_failure_cls @screenshot_failure_cls

View File

@@ -0,0 +1,25 @@
# Generated by Django 3.1.5 on 2021-02-08 16:02
from django.db import migrations
def add_default(apps, schema_editor):
CableType = apps.get_model('assets', 'CableType')
Connector = apps.get_model('assets', 'Connector')
for cable_type in CableType.objects.all():
if cable_type.plug is None:
cable_type.plug = Connector.first()
if cable_type.socket is None:
cable_type.socket = Connector.first()
cable_type.save()
class Migration(migrations.Migration):
dependencies = [
('assets', '0018_auto_20200415_1940'),
]
operations = [
migrations.RunPython(add_default, migrations.RunPython.noop)
]

View File

@@ -0,0 +1,50 @@
# Generated by Django 3.1.5 on 2021-02-08 16:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('assets', '0019_fix_cabletype'),
]
operations = [
migrations.AlterField(
model_name='assetstatus',
name='display_class',
field=models.CharField(blank=True, default='', help_text='HTML class to be appended to alter display of assets with this status, such as in the list.', max_length=80),
preserve_default=False,
),
migrations.AlterField(
model_name='cabletype',
name='plug',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='plug', to='assets.connector'),
),
migrations.AlterField(
model_name='cabletype',
name='socket',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='socket', to='assets.connector'),
),
migrations.AlterField(
model_name='supplier',
name='address',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='supplier',
name='email',
field=models.EmailField(blank=True, default='', max_length=254),
),
migrations.AlterField(
model_name='supplier',
name='notes',
field=models.TextField(blank=True, default=''),
),
migrations.AlterField(
model_name='supplier',
name='phone',
field=models.CharField(blank=True, default='', max_length=15),
),
]

View File

@@ -10,44 +10,44 @@ from RIGS.models import RevisionMixin, Profile
class AssetCategory(models.Model): class AssetCategory(models.Model):
name = models.CharField(max_length=80)
class Meta: class Meta:
verbose_name = 'Asset Category' verbose_name = 'Asset Category'
verbose_name_plural = 'Asset Categories' verbose_name_plural = 'Asset Categories'
ordering = ['name'] ordering = ['name']
name = models.CharField(max_length=80)
def __str__(self): def __str__(self):
return self.name return self.name
class AssetStatus(models.Model): class AssetStatus(models.Model):
name = models.CharField(max_length=80)
should_show = models.BooleanField(
default=True, help_text="Should this be shown by default in the asset list.")
display_class = models.CharField(max_length=80, blank=True, help_text="HTML class to be appended to alter display of assets with this status, such as in the list.")
class Meta: class Meta:
verbose_name = 'Asset Status' verbose_name = 'Asset Status'
verbose_name_plural = 'Asset Statuses' verbose_name_plural = 'Asset Statuses'
ordering = ['name'] ordering = ['name']
name = models.CharField(max_length=80)
should_show = models.BooleanField(
default=True, help_text="Should this be shown by default in the asset list.")
display_class = models.CharField(max_length=80, blank=True, null=True, help_text="HTML class to be appended to alter display of assets with this status, such as in the list.")
def __str__(self): def __str__(self):
return self.name return self.name
@reversion.register @reversion.register
class Supplier(models.Model, RevisionMixin): class Supplier(models.Model, RevisionMixin):
name = models.CharField(max_length=80)
phone = models.CharField(max_length=15, blank=True, default="")
email = models.EmailField(blank=True, default="")
address = models.TextField(blank=True, default="")
notes = models.TextField(blank=True, default="")
class Meta: class Meta:
ordering = ['name'] ordering = ['name']
name = models.CharField(max_length=80)
phone = models.CharField(max_length=15, blank=True, null=True)
email = models.EmailField(blank=True, null=True)
address = models.TextField(blank=True, null=True)
notes = models.TextField(blank=True, null=True)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('supplier_list') return reverse('supplier_list')
@@ -65,17 +65,16 @@ class Connector(models.Model):
return self.description return self.description
# Things are nullable that shouldn't be because I didn't properly fix the data structure when moving this to its own model...
class CableType(models.Model): class CableType(models.Model):
class Meta:
ordering = ['plug', 'socket', '-circuits']
circuits = models.IntegerField(default=1) circuits = models.IntegerField(default=1)
cores = models.IntegerField(default=3) cores = models.IntegerField(default=3)
plug = models.ForeignKey(Connector, on_delete=models.CASCADE, plug = models.ForeignKey(Connector, on_delete=models.CASCADE,
related_name='plug', null=True) related_name='plug')
socket = models.ForeignKey(Connector, on_delete=models.CASCADE, socket = models.ForeignKey(Connector, on_delete=models.CASCADE,
related_name='socket', null=True) related_name='socket')
class Meta:
ordering = ['plug', 'socket', '-circuits']
def __str__(self): def __str__(self):
if self.plug and self.socket: if self.plug and self.socket:
@@ -104,12 +103,6 @@ def get_available_asset_id(wanted_prefix=""):
@reversion.register @reversion.register
class Asset(models.Model, RevisionMixin): class Asset(models.Model, RevisionMixin):
class Meta:
ordering = ['asset_id_prefix', 'asset_id_number']
permissions = [
('asset_finance', 'Can see financial data for assets')
]
parent = models.ForeignKey(to='self', related_name='asset_parent', parent = models.ForeignKey(to='self', related_name='asset_parent',
blank=True, null=True, on_delete=models.SET_NULL) blank=True, null=True, on_delete=models.SET_NULL)
asset_id = models.CharField(max_length=15, unique=True) asset_id = models.CharField(max_length=15, unique=True)
@@ -143,12 +136,18 @@ class Asset(models.Model, RevisionMixin):
reversion_perm = 'assets.asset_finance' reversion_perm = 'assets.asset_finance'
def get_absolute_url(self): class Meta:
return reverse('asset_detail', kwargs={'pk': self.asset_id}) ordering = ['asset_id_prefix', 'asset_id_number']
permissions = [
('asset_finance', 'Can see financial data for assets')
]
def __str__(self): def __str__(self):
return "{} | {}".format(self.asset_id, self.description) return "{} | {}".format(self.asset_id, self.description)
def get_absolute_url(self):
return reverse('asset_detail', kwargs={'pk': self.asset_id})
def clean(self): def clean(self):
errdict = {} errdict = {}
if self.date_sold and self.date_acquired > self.date_sold: if self.date_sold and self.date_acquired > self.date_sold:

View File

@@ -43,7 +43,7 @@ class RIGSVersionTestCase(TestCase):
# Check the prev version is loaded correctly # Check the prev version is loaded correctly
previousVersion = current_version.parent previousVersion = current_version.parent
self.assertEqual(previousVersion._object_version.object.notes, None) assert previousVersion._object_version.object.notes == ''
# Check that finding the parent of the first version fails gracefully # Check that finding the parent of the first version fails gracefully
self.assertFalse(previousVersion.parent) self.assertFalse(previousVersion.parent)