mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-21 15:32:14 +00:00
System for allowing certain TrainingCategories to be trained by certain levels, regardless of supervisor status
I.e. the haulage department, ref #482. As generic as I can make it I think.
This commit is contained in:
@@ -23,9 +23,13 @@ class QualificationForm(forms.ModelForm):
|
|||||||
|
|
||||||
def clean_supervisor(self):
|
def clean_supervisor(self):
|
||||||
supervisor = self.cleaned_data['supervisor']
|
supervisor = self.cleaned_data['supervisor']
|
||||||
|
item = self.cleaned_data['item']
|
||||||
if supervisor.pk == self.cleaned_data['trainee'].pk:
|
if supervisor.pk == self.cleaned_data['trainee'].pk:
|
||||||
raise forms.ValidationError('One may not supervise oneself...')
|
raise forms.ValidationError('One may not supervise oneself...')
|
||||||
if not supervisor.is_supervisor:
|
if item.category.training_level:
|
||||||
|
if not supervisor.level_qualifications.filter(level=item.category.training_level):
|
||||||
|
raise forms.ValidationError('Selected supervising person is missing requisite training level to train in this department')
|
||||||
|
elif not supervisor.is_supervisor:
|
||||||
raise forms.ValidationError('Selected supervisor must actually *be* a supervisor...')
|
raise forms.ValidationError('Selected supervisor must actually *be* a supervisor...')
|
||||||
return supervisor
|
return supervisor
|
||||||
|
|
||||||
|
|||||||
19
training/migrations/0003_trainingcategory_training_level.py
Normal file
19
training/migrations/0003_trainingcategory_training_level.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 3.2.11 on 2022-01-25 12:58
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('training', '0002_alter_traininglevel_options'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='trainingcategory',
|
||||||
|
name='training_level',
|
||||||
|
field=models.ForeignKey(help_text='If this is set, any user with the selected level may pass out users within this category, regardless of other status', null=True, on_delete=django.db.models.deletion.CASCADE, to='training.traininglevel'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -15,22 +15,26 @@ class Trainee(Profile, RevisionMixin):
|
|||||||
def started_levels(self):
|
def started_levels(self):
|
||||||
return [level for level in TrainingLevel.objects.all() if level.percentage_complete(self) > 0 and level.pk not in self.level_qualifications.values_list('level', flat=True)]
|
return [level for level in TrainingLevel.objects.all() if level.percentage_complete(self) > 0 and level.pk not in self.level_qualifications.values_list('level', flat=True)]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def confirmed_levels(self):
|
||||||
|
return self.level_qualifications.exclude(confirmed_on=None).select_related('level')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_technician(self):
|
def is_technician(self):
|
||||||
return self.level_qualifications.exclude(confirmed_on=None).select_related('level') \
|
return self.confirmed_levels \
|
||||||
.filter(level__level=TrainingLevel.TECHNICIAN) \
|
.filter(level__level=TrainingLevel.TECHNICIAN) \
|
||||||
.exclude(level__department=TrainingLevel.HAULAGE) \
|
.exclude(level__department=TrainingLevel.HAULAGE) \
|
||||||
.exclude(level__department__isnull=True).exists()
|
.exclude(level__department__isnull=True).exists()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_driver(self):
|
def is_driver(self):
|
||||||
return self.level_qualifications.all().exclude(confirmed_on=None).select_related('level').filter(level__department=TrainingLevel.HAULAGE).exists()
|
return self.confirmed_levels.filter(level__department=TrainingLevel.HAULAGE).exists()
|
||||||
|
|
||||||
def get_records_of_depth(self, depth):
|
def get_records_of_depth(self, depth):
|
||||||
return self.qualifications_obtained.filter(depth=depth).select_related('item', 'trainee', 'supervisor')
|
return self.qualifications_obtained.filter(depth=depth).select_related('item', 'trainee', 'supervisor')
|
||||||
|
|
||||||
def is_user_qualified_in(self, item, required_depth):
|
def is_user_qualified_in(self, item, required_depth):
|
||||||
return self.qualifications_obtained.values('item', 'depth').filter(item=item).filter(depth__gte=required_depth).first() is not None # this is a somewhat ghetto version of get_or_none
|
return self.qualifications_obtained.values('item', 'depth').filter(item=item).filter(depth__gte=required_depth).exists()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('trainee_detail', kwargs={'pk': self.pk})
|
return reverse('trainee_detail', kwargs={'pk': self.pk})
|
||||||
@@ -47,6 +51,7 @@ class Trainee(Profile, RevisionMixin):
|
|||||||
class TrainingCategory(models.Model):
|
class TrainingCategory(models.Model):
|
||||||
reference_number = models.IntegerField(unique=True)
|
reference_number = models.IntegerField(unique=True)
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
|
training_level = models.ForeignKey('TrainingLevel', on_delete=models.CASCADE, null=True, help_text="If this is set, any user with the selected level may pass out users within this category, regardless of other status")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.reference_number}. {self.name}"
|
return f"{self.reference_number}. {self.name}"
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group form-row">
|
<div class="form-group form-row">
|
||||||
<label for="supervisor" class="col-sm-2 col-form-label">Supervisor</label>
|
<label for="supervisor" class="col-sm-2 col-form-label">Supervisor</label>
|
||||||
<select name="supervisor" id="supervisor_id" class="form-control selectpicker custom-select col-sm-10" data-live-search="true" data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials&filters=is_supervisor" required>
|
<select name="supervisor" id="supervisor_id" class="form-control selectpicker custom-select col-sm-10" data-live-search="true" data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials" required>
|
||||||
{% if object.supervisor %}
|
{% if object.supervisor %}
|
||||||
<option value="{{object.supervisor.pk}}" selected>{{object.supervisor}}</option>
|
<option value="{{object.supervisor.pk}}" selected>{{object.supervisor}}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
class="form-control" id="id_search_text"/>
|
class="form-control" id="id_search_text"/>
|
||||||
<span class="input-group-append">{% button 'search' id="id_search" %}</span>
|
<span class="input-group-append">{% button 'search' id="id_search" %}</span>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary mt-2 {% if request.GET.is_supervisor %}active{%endif%}" data-toggle="button" aria-pressed="false" name="is_supervisor" value="{% if request.GET.is_supervisor %}{% else %}True{% endif %}">
|
<button type="submit" class="btn btn-primary mt-2 {% if request.GET.is_supervisor %}active{%endif%}" data-toggle="button" aria-pressed="{% if request.GET.is_supervisor %}true{%endif%}" name="is_supervisor" value="{% if request.GET.is_supervisor %}{% else %}True{% endif %}">
|
||||||
Only Supervisors
|
Only Supervisors
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in New Issue
Block a user