Merged in [19139] from rjsparks@nostrum.com:

Refine volunteer list view. Show rfc8989 paths.
 - Legacy-Id: 19147
Note: SVN reference [19139] has been migrated to Git commit 06f6b12b18
This commit is contained in:
Robert Sparks 2021-06-23 15:54:45 +00:00
commit 2689670546
4 changed files with 109 additions and 26 deletions

View file

@ -41,7 +41,8 @@ from ietf.nomcom.factories import NomComFactory, FeedbackFactory, TopicFactory,
key
from ietf.nomcom.utils import get_nomcom_by_year, make_nomineeposition, \
get_hash_nominee_position, is_eligible, list_eligible, \
get_eligibility_date, suggest_affiliation
get_eligibility_date, suggest_affiliation, \
decorate_volunteers_with_qualifications
from ietf.person.factories import PersonFactory, EmailFactory
from ietf.person.models import Email, Person
from ietf.stats.models import MeetingRegistration
@ -2529,3 +2530,49 @@ class VolunteerTests(TestCase):
self.assertEqual(suggest_affiliation(person), 'volunteer_affil')
MeetingRegistrationFactory(person=person, affiliation='meeting_affil')
self.assertEqual(suggest_affiliation(person), 'meeting_affil')
class VolunteerDecoratorUnitTests(TestCase):
def test_decorate_volunteers_with_qualifications(self):
nomcom = NomComFactory(group__acronym='nomcom2021', populate_personnel=False, first_call_for_volunteers=datetime.date(2021,5,15))
elig_date = get_eligibility_date(nomcom)
Role.objects.filter(name_id__in=('chair','secr')).delete()
meeting_person = PersonFactory()
meetings = [MeetingFactory(number=number, date=date, type_id='ietf') for number,date in [
('110', datetime.date(2021, 3, 6)),
('109', datetime.date(2020, 11, 14)),
('108', datetime.date(2020, 7, 25)),
('107', datetime.date(2020, 3, 21)),
('106', datetime.date(2019, 11, 16)),
]]
for m in meetings:
MeetingRegistrationFactory(meeting=m,person=meeting_person)
nomcom.volunteer_set.create(person=meeting_person)
office_person = PersonFactory()
RoleHistoryFactory(
name_id='chair',
group__time= elig_date - datetime.timedelta(days=365),
group__group__state_id='conclude',
person=office_person,
)
nomcom.volunteer_set.create(person=office_person)
author_person = PersonFactory()
for i in range(2):
da = WgDocumentAuthorFactory(person=author_person)
DocEventFactory(type='published_rfc',doc=da.document,time=datetime.date(elig_date.year-3,elig_date.month,elig_date.day))
nomcom.volunteer_set.create(person=author_person)
volunteers = nomcom.volunteer_set.all()
decorate_volunteers_with_qualifications(volunteers,nomcom=nomcom)
self.assertEqual(len(volunteers), 3)
for v in volunteers:
if v.person == meeting_person:
self.assertEqual(v.qualifications,'path_1')
if v.person == office_person:
self.assertEqual(v.qualifications,'path_2')
if v.person == author_person:
self.assertEqual(v.qualifications,'path_3')

View file

@ -500,6 +500,25 @@ def list_eligible(nomcom=None, date=None, base_qs=None):
else:
return Person.objects.none()
def decorate_volunteers_with_qualifications(volunteers, nomcom=None, date=None, base_qs=None):
if not base_qs:
base_qs = Person.objects.all()
eligibility_date = get_eligibility_date(nomcom, date)
if eligibility_date.year == 2021:
three_of_five_qs, officer_qs, author_qs = get_8989_eligibility_querysets(eligibility_date, base_qs)
for v in volunteers:
qualifications = []
if v.person in three_of_five_qs:
qualifications.append('path_1')
if v.person in officer_qs:
qualifications.append('path_2')
if v.person in author_qs:
qualifications.append('path_3')
v.qualifications = ", ".join(qualifications)
else:
for v in volunteers:
v.qualifications = ''
def list_eligible_8713(date, base_qs=None):
if not base_qs:
base_qs = Person.objects.all()
@ -512,7 +531,7 @@ def list_eligible_8788(date, base_qs=None):
previous_five = Meeting.objects.filter(number__in=['102','103','104','105','106'])
return remove_disqualified(three_of_five_eligible(previous_five=previous_five, queryset=base_qs))
def list_eligible_8989(date, base_qs=None):
def get_8989_eligibility_querysets(date, base_qs):
if not base_qs:
base_qs = Person.objects.all()
@ -545,13 +564,17 @@ def list_eligible_8989(date, base_qs=None):
).annotate(
document_author_count = Count('documentauthor')
).filter(document_author_count__gte=2)
return three_of_five_qs, officer_qs, author_qs
# Would be nice to use queryset union here, but the annotations make that difficult
return remove_disqualified(Person.objects.filter(pk__in=
set(three_of_five_qs.values_list('pk',flat=True)).union(
set(officer_qs.values_list('pk',flat=True))).union(
set(author_qs.values_list('pk',flat=True)))
))
def list_eligible_8989(date, base_qs=None):
if not base_qs:
base_qs = Person.objects.all()
three_of_five_qs, officer_qs, author_qs = get_8989_eligibility_querysets(date, base_qs)
# Would be nice to use queryset union here, but the annotations in the three existing querysets make that difficult
three_of_five_pks = three_of_five_qs.values_list('pk',flat=True)
officer_pks = officer_qs.values_list('pk',flat=True)
author_pks = author_qs.values_list('pk',flat=True)
return remove_disqualified(Person.objects.filter(pk__in=set(three_of_five_pks).union(set(officer_pks)).union(set(author_pks))))
def get_eligibility_date(nomcom=None, date=None):
if date:

View file

@ -36,6 +36,7 @@ from ietf.nomcom.models import (Position, NomineePosition, Nominee, Feedback, No
FeedbackLastSeen, Topic, TopicFeedbackLastSeen, )
from ietf.nomcom.utils import (get_nomcom_by_year, store_nomcom_private_key, suggest_affiliation,
get_hash_nominee_position, send_reminder_to_nominees, list_eligible,
decorate_volunteers_with_qualifications,
HOME_TEMPLATE, NOMINEE_ACCEPT_REMINDER_TEMPLATE,NOMINEE_QUESTIONNAIRE_REMINDER_TEMPLATE, )
from ietf.ietfauth.utils import role_required
@ -1323,6 +1324,7 @@ def volunteers(request, year, public=False):
eligible = list_eligible(nomcom)
for v in volunteers:
v.eligible = v.person in eligible
decorate_volunteers_with_qualifications(volunteers,nomcom=nomcom)
volunteers = sorted(volunteers,key=lambda v:(not v.eligible,v.person.last_name()))
return render(request, 'nomcom/volunteers.html', dict(year=year, nomcom=nomcom, volunteers=volunteers, public=public))

View file

@ -14,25 +14,36 @@
{% origin %}
<h2>Volunteers for {{ nomcom.group }}</h2>
<table class="table table-condensed table-striped tablesorter">
<thead>
<th>Eligible</th>
<th>Last Name</th>
<th>First Name</th>
<th>Affiliation</th>
<th>Email Addresses</th>
</thead>
{% for v in volunteers %}
<tr>
<td>{{v.eligible|yesno}}
<td><a href="{% url 'ietf.person.views.profile' v.person.name %}">{{v.person.last_name}}</a></td>
<td>{{v.person.first_name}}</td>
<td>{{v.affiliation}}</td>
<td>{% for e in v.person.email_set.all %}{{e.address}}{% if not forloop.last %}, {% endif %}{% endfor %}</td>
</tr>
{% regroup volunteers by eligible as volunteers_by_eligibility %}
{% for eligibility_group in volunteers_by_eligibility %}
<div class="panel panel-default">
<div class="panel-heading">{{ eligibility_group.grouper|yesno:"Eligible, Not Eligible"}}</div>
<div class="panel-body">
<table class="table table-condensed table-striped tablesorter">
<thead>
<th></th>
<th>Last Name</th>
<th>First Name</th>
<th>Affiliation</th>
<th>Primary Email Address</th>
<th>Qualifications</th>
</thead>
{% for v in eligibility_group.list %}
<tr>
<td>{{ forloop.counter }}</td>
<td><a href="{% url 'ietf.person.views.profile' v.person.name %}">{{v.person.last_name}}</a></td>
<td>{{v.person.first_name}}</td>
<td>{{v.affiliation}}</td>
<td>{{v.person.email}}</td>
<td>{{v.qualifications}}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
</table>
{% endblock nomcom_content %}
{% block js %}