Add event checkin functionality, seperate power tests into a different form (#536)

* Split power related parts of event checklist into a seperate form

* Revamp H&S overview, remove individual lists.

They were not a good thing.

* Remove old 'vehicle/crew' stuff

* Very initial version of checkin form

* Further work on checkin, add role field etc

* Fix tests after form split

* Add ability to edit checkins, more validation

* Basic checkin/out logic complete

* Add homepage checkin for events happening now

* Minor improvement to homepage UI

* Checkin button turns into checkout button where applicable

* UI work

* Clicking check out does not redirect the user

* Register check in model with the admin site

* Add power record status chip, checklist status chip displays number of checklists

* Minor fixes

* Implement codedoctor suggestions

* pep8

* Add data migration for crew/vehicles

* Checkin only requires login (no perms) and block users from editing other checkins at Django level
This commit is contained in:
2023-05-19 10:28:51 +00:00
committed by GitHub
parent 724762a1e8
commit 01a0b8f831
30 changed files with 1179 additions and 870 deletions

View File

@@ -44,7 +44,7 @@ class EventForm(forms.ModelForm):
return simplejson.dumps(items)
def __init__(self, *args, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.fields['items_json'].initial = self._get_items_json
self.fields['start_date'].widget.format = '%Y-%m-%d'
@@ -200,86 +200,41 @@ class EventChecklistForm(forms.ModelForm):
related_models = {
'venue': models.Venue,
'power_mic': models.Profile,
}
# Two possible formats
def parsedatetime(self, date_string):
try:
return timezone.make_aware(datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%S'))
except ValueError:
return timezone.make_aware(datetime.strptime(date_string, '%Y-%m-%dT%H:%M'))
# There's probably a thousand better ways to do this, but this one is mine
def clean(self):
vehicles = {key: val for key, val in self.data.items()
if key.startswith('vehicle')}
for key in vehicles:
pk = int(key.split('_')[1])
driver_key = 'driver_' + str(pk)
if (self.data[driver_key] == ''):
raise forms.ValidationError('Add a driver to vehicle ' + str(pk), code='vehicle_mismatch')
else:
try:
item = models.EventChecklistVehicle.objects.get(pk=pk)
except models.EventChecklistVehicle.DoesNotExist:
item = models.EventChecklistVehicle()
item.vehicle = vehicles['vehicle_' + str(pk)]
item.driver = models.Profile.objects.get(pk=self.data[driver_key])
item.full_clean('checklist')
# item does not have a database pk yet as it isn't saved
self.items['v' + str(pk)] = item
crewmembers = {key: val for key, val in self.data.items()
if key.startswith('crewmember')}
other_fields = ['start', 'role', 'end']
for key in crewmembers:
pk = int(key.split('_')[1])
for field in other_fields:
value = self.data[f'{field}_{pk}']
if value == '':
raise forms.ValidationError(f'Add a {field} to crewmember {pk}', code=f'{field}_mismatch')
try:
item = models.EventChecklistCrew.objects.get(pk=pk)
except models.EventChecklistCrew.DoesNotExist:
item = models.EventChecklistCrew()
item.crewmember = models.Profile.objects.get(pk=self.data['crewmember_' + str(pk)])
item.start = self.parsedatetime(self.data['start_' + str(pk)])
item.role = self.data['role_' + str(pk)]
item.end = self.parsedatetime(self.data['end_' + str(pk)])
item.full_clean('checklist')
# item does not have a database pk yet as it isn't saved
self.items['c' + str(pk)] = item
return super(EventChecklistForm, self).clean()
def save(self, commit=True):
checklist = super(EventChecklistForm, self).save(commit=False)
if (commit):
# Remove all existing, to be recreated from the form
checklist.vehicles.all().delete()
checklist.crew.all().delete()
checklist.save()
for key in self.items:
item = self.items[key]
reversion.add_to_revision(item)
# finish and save new database items
item.checklist = checklist
item.full_clean()
item.save()
self.items.clear()
return checklist
class Meta:
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']
class EventCheckInForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['time'].initial = timezone.now()
self.fields['role'].initial = "Crew"
class Meta:
model = models.EventCheckIn
fields = '__all__'
exclude = ['end_time']
class EditCheckInForm(forms.ModelForm):
class Meta:
model = models.EventCheckIn
fields = '__all__'