connect the new calculations to the UI. Clean flakes.
- Legacy-Id: 18974
This commit is contained in:
parent
e3476f5bdb
commit
fe82f4d696
|
@ -13,7 +13,7 @@ from django.conf import settings
|
||||||
|
|
||||||
from ietf.doc.models import ( Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor,
|
from ietf.doc.models import ( Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor,
|
||||||
StateDocEvent, BallotPositionDocEvent, BallotDocEvent, BallotType, IRSGBallotDocEvent, TelechatDocEvent,
|
StateDocEvent, BallotPositionDocEvent, BallotDocEvent, BallotType, IRSGBallotDocEvent, TelechatDocEvent,
|
||||||
DocumentActionHolder, DocumentAuthor)
|
DocumentActionHolder)
|
||||||
from ietf.group.models import Group
|
from ietf.group.models import Group
|
||||||
|
|
||||||
def draft_name_generator(type_id,group,n):
|
def draft_name_generator(type_id,group,n):
|
||||||
|
|
|
@ -18,12 +18,11 @@ from django.utils.safestring import mark_safe
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from ietf.dbtemplate.models import DBTemplate
|
from ietf.dbtemplate.models import DBTemplate
|
||||||
from ietf.meeting.models import Session, Meeting, SchedulingEvent, TimeSlot, Constraint, SchedTimeSessAssignment
|
from ietf.meeting.models import Session, SchedulingEvent, TimeSlot, Constraint, SchedTimeSessAssignment
|
||||||
from ietf.group.models import Group, Role
|
from ietf.group.models import Group
|
||||||
from ietf.group.utils import can_manage_materials
|
from ietf.group.utils import can_manage_materials
|
||||||
from ietf.name.models import SessionStatusName, ConstraintName
|
from ietf.name.models import SessionStatusName, ConstraintName
|
||||||
from ietf.nomcom.utils import DISQUALIFYING_ROLE_QUERY_EXPRESSION
|
from ietf.person.models import Person
|
||||||
from ietf.person.models import Person, Email
|
|
||||||
from ietf.secr.proceedings.proc_utils import import_audio_files
|
from ietf.secr.proceedings.proc_utils import import_audio_files
|
||||||
|
|
||||||
def session_time_for_sorting(session, use_meeting_date):
|
def session_time_for_sorting(session, use_meeting_date):
|
||||||
|
@ -171,25 +170,6 @@ def finalize(meeting):
|
||||||
meeting.save()
|
meeting.save()
|
||||||
return
|
return
|
||||||
|
|
||||||
def attended_ietf_meetings(person):
|
|
||||||
email_addresses = Email.objects.filter(person=person).values_list('address',flat=True)
|
|
||||||
return Meeting.objects.filter(
|
|
||||||
type='ietf',
|
|
||||||
meetingregistration__email__in=email_addresses,
|
|
||||||
meetingregistration__attended=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def attended_in_last_five_ietf_meetings(person, date=datetime.datetime.today()):
|
|
||||||
previous_five = Meeting.objects.filter(type='ietf',date__lte=date).order_by('-date')[:5]
|
|
||||||
attended = attended_ietf_meetings(person)
|
|
||||||
return set(previous_five).intersection(attended)
|
|
||||||
|
|
||||||
def is_nomcom_eligible(person, date=datetime.date.today()):
|
|
||||||
attended = attended_in_last_five_ietf_meetings(person, date)
|
|
||||||
disqualifying_roles = Role.objects.filter(person=person).filter(DISQUALIFYING_ROLE_QUERY_EXPRESSION)
|
|
||||||
return len(attended)>=3 and not disqualifying_roles.exists()
|
|
||||||
|
|
||||||
|
|
||||||
def sort_accept_tuple(accept):
|
def sort_accept_tuple(accept):
|
||||||
tup = []
|
tup = []
|
||||||
if accept:
|
if accept:
|
||||||
|
|
|
@ -480,6 +480,10 @@ def create_feedback_email(nomcom, msg):
|
||||||
class EncryptedException(Exception):
|
class EncryptedException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def remove_disqualified(queryset):
|
||||||
|
disqualified_roles = Role.objects.filter(DISQUALIFYING_ROLE_QUERY_EXPRESSION)
|
||||||
|
return queryset.exclude(role__in=disqualified_roles)
|
||||||
|
|
||||||
def is_eligible(person, nomcom=None, date=None):
|
def is_eligible(person, nomcom=None, date=None):
|
||||||
return list_eligible(nomcom=nomcom, date=date, base_qs=Person.objects.filter(pk=person.pk)).exists()
|
return list_eligible(nomcom=nomcom, date=date, base_qs=Person.objects.filter(pk=person.pk)).exists()
|
||||||
|
|
||||||
|
@ -500,13 +504,13 @@ def list_eligible_8713(date, base_qs=None):
|
||||||
if not base_qs:
|
if not base_qs:
|
||||||
base_qs = Person.objects.all()
|
base_qs = Person.objects.all()
|
||||||
previous_five = previous_five_meetings(date)
|
previous_five = previous_five_meetings(date)
|
||||||
return three_of_five_eligible(previous_five=previous_five, queryset=base_qs)
|
return remove_disqualified(three_of_five_eligible(previous_five=previous_five, queryset=base_qs))
|
||||||
|
|
||||||
def list_eligible_8788(date, base_qs=None):
|
def list_eligible_8788(date, base_qs=None):
|
||||||
if not base_qs:
|
if not base_qs:
|
||||||
base_qs = Person.objects.all()
|
base_qs = Person.objects.all()
|
||||||
previous_five = Meeting.objects.filter(number__in=['102','103','104','105','106'])
|
previous_five = Meeting.objects.filter(number__in=['102','103','104','105','106'])
|
||||||
return three_of_five_eligible(previous_five=previous_five, queryset=base_qs)
|
return remove_disqualified(three_of_five_eligible(previous_five=previous_five, queryset=base_qs))
|
||||||
|
|
||||||
def list_eligible_8989(date, base_qs=None):
|
def list_eligible_8989(date, base_qs=None):
|
||||||
if not base_qs:
|
if not base_qs:
|
||||||
|
@ -542,12 +546,12 @@ def list_eligible_8989(date, base_qs=None):
|
||||||
document_author_count = Count('documentauthor')
|
document_author_count = Count('documentauthor')
|
||||||
).filter(document_author_count__gte=2)
|
).filter(document_author_count__gte=2)
|
||||||
|
|
||||||
# return three_of_five_qs.union(officer_qs, author_qs)
|
# Would be nice to use queryset union here, but the annotations make that difficult
|
||||||
return Person.objects.filter(pk__in=
|
return remove_disqualified(Person.objects.filter(pk__in=
|
||||||
set(three_of_five_qs.values_list('pk',flat=True)).union(
|
set(three_of_five_qs.values_list('pk',flat=True)).union(
|
||||||
set(officer_qs.values_list('pk',flat=True))).union(
|
set(officer_qs.values_list('pk',flat=True))).union(
|
||||||
set(author_qs.values_list('pk',flat=True)))
|
set(author_qs.values_list('pk',flat=True)))
|
||||||
)
|
))
|
||||||
|
|
||||||
def get_eligibility_date(nomcom=None, date=None):
|
def get_eligibility_date(nomcom=None, date=None):
|
||||||
if date:
|
if date:
|
||||||
|
|
|
@ -24,7 +24,6 @@ from ietf.dbtemplate.views import group_template_edit, group_template_show
|
||||||
from ietf.name.models import NomineePositionStateName, FeedbackTypeName
|
from ietf.name.models import NomineePositionStateName, FeedbackTypeName
|
||||||
from ietf.group.models import Group, GroupEvent, Role
|
from ietf.group.models import Group, GroupEvent, Role
|
||||||
from ietf.message.models import Message
|
from ietf.message.models import Message
|
||||||
from ietf.meeting.models import Meeting
|
|
||||||
|
|
||||||
from ietf.nomcom.decorators import nomcom_private_key_required
|
from ietf.nomcom.decorators import nomcom_private_key_required
|
||||||
from ietf.nomcom.forms import (NominateForm, NominateNewPersonForm, FeedbackForm, QuestionnaireForm,
|
from ietf.nomcom.forms import (NominateForm, NominateNewPersonForm, FeedbackForm, QuestionnaireForm,
|
||||||
|
@ -36,12 +35,11 @@ from ietf.nomcom.forms import (NominateForm, NominateNewPersonForm, FeedbackForm
|
||||||
from ietf.nomcom.models import (Position, NomineePosition, Nominee, Feedback, NomCom, ReminderDates,
|
from ietf.nomcom.models import (Position, NomineePosition, Nominee, Feedback, NomCom, ReminderDates,
|
||||||
FeedbackLastSeen, Topic, TopicFeedbackLastSeen, )
|
FeedbackLastSeen, Topic, TopicFeedbackLastSeen, )
|
||||||
from ietf.nomcom.utils import (get_nomcom_by_year, store_nomcom_private_key,
|
from ietf.nomcom.utils import (get_nomcom_by_year, store_nomcom_private_key,
|
||||||
get_hash_nominee_position, send_reminder_to_nominees,
|
get_hash_nominee_position, send_reminder_to_nominees, list_eligible,
|
||||||
HOME_TEMPLATE, NOMINEE_ACCEPT_REMINDER_TEMPLATE,NOMINEE_QUESTIONNAIRE_REMINDER_TEMPLATE,
|
HOME_TEMPLATE, NOMINEE_ACCEPT_REMINDER_TEMPLATE,NOMINEE_QUESTIONNAIRE_REMINDER_TEMPLATE, )
|
||||||
DISQUALIFYING_ROLE_QUERY_EXPRESSION)
|
|
||||||
from ietf.ietfauth.utils import role_required
|
from ietf.ietfauth.utils import role_required
|
||||||
from ietf.person.models import Person
|
from ietf.person.models import Person
|
||||||
from ietf.utils import log
|
|
||||||
from ietf.utils.response import permission_denied
|
from ietf.utils.response import permission_denied
|
||||||
|
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
@ -1275,31 +1273,7 @@ def extract_email_lists(request, year):
|
||||||
def eligible(request, year):
|
def eligible(request, year):
|
||||||
nomcom = get_nomcom_by_year(year)
|
nomcom = get_nomcom_by_year(year)
|
||||||
|
|
||||||
# This should probably be refined. If the nomcom year is this year, then
|
eligible_persons = list(list_eligible(nomcom=nomcom))
|
||||||
# today's date makes sense; for previous nomcoms, we should probably get
|
|
||||||
# the date of the announcement of the Call for Volunteers, instead
|
|
||||||
date = datetime.date.today()
|
|
||||||
previous_five = ( Meeting.objects.filter(type='ietf',date__lte=date)
|
|
||||||
.exclude(city='').exclude(city='Virtual')
|
|
||||||
.order_by('-date')[:5] )
|
|
||||||
log.assertion("len(previous_five) == 5")
|
|
||||||
attendees = {}
|
|
||||||
potentials = set()
|
|
||||||
for m in previous_five:
|
|
||||||
registration_emails = m.meetingregistration_set.filter(attended=True).values_list('email',flat=True)
|
|
||||||
attendees[m] = Person.objects.filter(email__address__in=registration_emails).distinct()
|
|
||||||
# See RFC8713 section 4.15
|
|
||||||
disqualified_roles = Role.objects.filter(DISQUALIFYING_ROLE_QUERY_EXPRESSION)
|
|
||||||
potentials.update(attendees[m].exclude(role__in=disqualified_roles))
|
|
||||||
eligible_persons = []
|
|
||||||
for p in potentials:
|
|
||||||
count = 0
|
|
||||||
for m in previous_five:
|
|
||||||
if p in attendees[m]:
|
|
||||||
count += 1
|
|
||||||
if count >= 3:
|
|
||||||
eligible_persons.append(p)
|
|
||||||
|
|
||||||
eligible_persons.sort(key=lambda p: p.last_name() )
|
eligible_persons.sort(key=lambda p: p.last_name() )
|
||||||
|
|
||||||
return render(request, 'nomcom/eligible.html',
|
return render(request, 'nomcom/eligible.html',
|
||||||
|
|
|
@ -6,14 +6,14 @@ from django import template
|
||||||
|
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from ietf.meeting.utils import is_nomcom_eligible as util_is_nomcom_eligible
|
from ietf.nomcom.utils import is_eligible
|
||||||
from ietf.person.models import Alias
|
from ietf.person.models import Alias
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def is_nomcom_eligible(person, date=datetime.date.today()):
|
def is_nomcom_eligible(person, date=datetime.date.today()):
|
||||||
return util_is_nomcom_eligible(person,date)
|
return is_eligible(person=person,date=date)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def person_by_name(name):
|
def person_by_name(name):
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from ietf.stats.utils import find_meetingregistration_person_issues
|
from ietf.stats.utils import find_meetingregistration_person_issues
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from ietf.stats.utils import repair_meetingregistration_person
|
from ietf.stats.utils import repair_meetingregistration_person
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import re
|
||||||
import requests
|
import requests
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.db.models import F, Q
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
{% origin %}
|
{% origin %}
|
||||||
<h2>Eligible People for {{ nomcom.group }}</h2>
|
<h2>Eligible People for {{ nomcom.group }}</h2>
|
||||||
|
|
||||||
<p class="alert alert-info">
|
|
||||||
This calculation is experimental and is likely wrong. Check carefully against the secretariat eligibility tools if it matters. This page lists people who would be nomcom eligible if the selection were made <em>today</em>. Thus if today is not between the spring and summer IETF meetings, the list won't reflect eligibility at the time actual selections will be made.
|
|
||||||
</p>
|
|
||||||
<table class="table table-condensed table-striped tablesorter">
|
<table class="table table-condensed table-striped tablesorter">
|
||||||
<thead>
|
<thead>
|
||||||
<th>Last Name</th>
|
<th>Last Name</th>
|
||||||
|
|
|
@ -69,17 +69,16 @@
|
||||||
<div class="col-sm-1 form-control-static">{{person|is_nomcom_eligible|yesno:'Yes,No,No'}}</div>
|
<div class="col-sm-1 form-control-static">{{person|is_nomcom_eligible|yesno:'Yes,No,No'}}</div>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<p class="alert alert-info form-control-static">
|
<p class="alert alert-info form-control-static">
|
||||||
This calculation is EXPERIMENTAL.<br/>
|
If you believe this calculation is incorrect, make sure you've added all the
|
||||||
|
|
||||||
If you believe it is incorrect, make sure you've added all the
|
|
||||||
email addresses you've registered for IETF meetings with to the
|
email addresses you've registered for IETF meetings with to the
|
||||||
list below.<br/>
|
list below.<br/>
|
||||||
|
|
||||||
If you've done so and the calculation is still incorrect, please
|
If you've done so and the calculation is still incorrect, please
|
||||||
send a note to
|
send a note to
|
||||||
<a href="mailto:{{settings.SECRETARIAT_INFO_EMAIL}}">{{settings.SECRETARIAT_INFO_EMAIL}}</a>.<br/>
|
<a href="mailto:{{settings.SECRETARIAT_SUPPORT_EMAIL}}">{{settings.SECRETARIAT_SUPPORT_EMAIL}}</a>.<br/>
|
||||||
See <a href="{% url 'ietf.doc.views_doc.document_main' name='rfc7437'%}">RFC 7437</a>
|
See <a href="{% url 'ietf.doc.views_doc.document_main' name='rfc8713'%}">RFC 8713</a>
|
||||||
for eligibility requirements.
|
for eligibility requirements.
|
||||||
|
For the 2021 nomcom, see also <a href="{% url 'ietf.doc.views_doc.document_main' name='rfc8989' %}">RFC 8989</a>.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -181,7 +180,7 @@
|
||||||
dagger symbol (<strong>†</strong>) next to it, or listed on your
|
dagger symbol (<strong>†</strong>) next to it, or listed on your
|
||||||
<a href="{% url 'ietf.community.views.view_list' user.username %}">notification subscription page</a>. Most of this
|
<a href="{% url 'ietf.community.views.view_list' user.username %}">notification subscription page</a>. Most of this
|
||||||
information can be edited or removed on these pages. There are some exceptions, such
|
information can be edited or removed on these pages. There are some exceptions, such
|
||||||
as photos, which currently require an email to <a href="mailto:{{settings.SECRETARIAT_INFO_EMAIL}}">the Secretariat</a>
|
as photos, which currently require an email to <a href="mailto:{{settings.SECRETARIAT_SUPPORT_EMAIL}}">the Secretariat</a>
|
||||||
if you wish to update or remove the information.
|
if you wish to update or remove the information.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
Loading…
Reference in a new issue