Repository: ietf-tools/datatracker

Issue:
The NomCom chair is not eligible for NomCom
### Describe the issue

I had to remove myself manually after I had volunteered during meeting registration prior to being appointed.

(Rich failed to notice that he was on the list at first.  I only noticed because of that problem, so I made a point of give the list a once-over.)

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)


Discussion:
Agreed that this is something the datatracker should take care of since it knows who the nomcom chairs are.

But, be aware that there are several ways that someone can be disqualified that the datatracker _doesn't_ know about. (such as being a contractor to the LLC, or officers of organizations that the RFC calls out that we do not model in the datatracker).

Good points.  I think that in a lot of those cases, the people involved will not volunteer.  Or at least it would be less common.

Resolving patch:
diff --git a/ietf/nomcom/utils.py b/ietf/nomcom/utils.py
--- a/ietf/nomcom/utils.py
+++ b/ietf/nomcom/utils.py
@@ -1,4 +1,4 @@
-# Copyright The IETF Trust 2012-2022, All Rights Reserved
+# Copyright The IETF Trust 2012-2023, All Rights Reserved
 # -*- coding: utf-8 -*-
 
 
@@ -66,8 +66,11 @@
                         ]
 
 # See RFC8713 section 4.15
+# This potentially over-disqualifies past nomcom chairs if some 
+# nomcom 2+ nomcoms ago is still in the active state
 DISQUALIFYING_ROLE_QUERY_EXPRESSION = (   Q(group__acronym__in=['isocbot', 'ietf-trust', 'llc-board', 'iab'], name_id__in=['member', 'chair'])
                                         | Q(group__type_id='area', group__state='active',name_id='ad')
+                                        | Q(group__type_id='nomcom', group__state='active', name_id='chair')
                                       )
 
 


Test patch:
diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py
--- a/ietf/nomcom/tests.py
+++ b/ietf/nomcom/tests.py
@@ -2419,6 +2419,7 @@ def setUp(self):
         self.eligible_people = list()
         self.ineligible_people = list()
 
+        # Section 4.14 qualification criteria
         for combo_len in range(0,6):
             for combo in combinations(meetings,combo_len):
                 p = PersonFactory()
@@ -2429,6 +2430,18 @@ def setUp(self):
                 else:
                     self.eligible_people.append(p)
 
+        # Section 4.15 disqualification criteria
+        def ineligible_person_with_role(**kwargs):
+            p = RoleFactory(**kwargs).person
+            for m in meetings:
+                MeetingRegistrationFactory(person=p, meeting=m, attended=True)
+            self.ineligible_people.append(p)
+        for group in ['isocbot', 'ietf-trust', 'llc-board', 'iab']:
+            for role in ['member', 'chair']:
+                ineligible_person_with_role(group__acronym=group, name_id=role)
+        ineligible_person_with_role(group__type_id='area', group__state_id='active',name_id='ad')
+        ineligible_person_with_role(group=self.nomcom.group, name_id='chair')
+
         # No-one is eligible for the other_nomcom
         self.other_nomcom = NomComFactory(group__acronym='nomcom2018',first_call_for_volunteers=datetime.date(2018,5,1))