diff --git a/ietf/doc/forms.py b/ietf/doc/forms.py index 8bb4a1b73..e48d1b40e 100644 --- a/ietf/doc/forms.py +++ b/ietf/doc/forms.py @@ -21,7 +21,7 @@ class TelechatForm(forms.Form): from ietf.person.models import Person class AdForm(forms.Form): - ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), + ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active", role__group__type='area').order_by('name'), label="Shepherding AD", empty_label="(None)", required=True) def __init__(self, *args, **kwargs): diff --git a/ietf/doc/mails.py b/ietf/doc/mails.py index 31e9f4c1f..99d6d5af4 100644 --- a/ietf/doc/mails.py +++ b/ietf/doc/mails.py @@ -328,7 +328,7 @@ def email_ballot_undeferred(request, doc, by, telechat_date): telechat_date=telechat_date)) def generate_issue_ballot_mail(request, doc, ballot): - active_ads = Person.objects.filter(role__name="ad", role__group__state="active").distinct() + active_ads = Person.objects.filter(role__name="ad", role__group__state="active", role__group__type="area").distinct() positions = BallotPositionDocEvent.objects.filter(doc=doc, type="changed_ballot_position", ballot=ballot).order_by("-time", '-id').select_related('ad') diff --git a/ietf/doc/models.py b/ietf/doc/models.py index f9bc10746..79f0fe3ab 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -744,7 +744,7 @@ class BallotDocEvent(DocEvent): def active_ad_positions(self): """Return dict mapping each active AD to a current ballot position (or None if they haven't voted).""" - active_ads = list(Person.objects.filter(role__name="ad", role__group__state="active")) + active_ads = list(Person.objects.filter(role__name="ad", role__group__state="active", role__group__type="area")) res = {} positions = BallotPositionDocEvent.objects.filter(type="changed_ballot_position",ad__in=active_ads, ballot=self).select_related('ad', 'pos').order_by("-time", "-id") @@ -763,7 +763,7 @@ class BallotDocEvent(DocEvent): positions = [] seen = {} - active_ads = list(Person.objects.filter(role__name="ad", role__group__state="active").distinct()) + active_ads = list(Person.objects.filter(role__name="ad", role__group__state="active", role__group__type="area").distinct()) for e in BallotPositionDocEvent.objects.filter(type="changed_ballot_position", ballot=self).select_related('ad', 'pos').order_by("-time", '-id'): if e.ad not in seen: e.old_ad = e.ad not in active_ads diff --git a/ietf/doc/utils_charter.py b/ietf/doc/utils_charter.py index 796920ba1..4d5e17ee9 100644 --- a/ietf/doc/utils_charter.py +++ b/ietf/doc/utils_charter.py @@ -154,7 +154,7 @@ def default_review_text(group, charter, by): return e def generate_issue_ballot_mail(request, doc, ballot): - active_ads = Person.objects.filter(email__role__name="ad", email__role__group__state="active").distinct() + active_ads = Person.objects.filter(email__role__name="ad", email__role__group__state="active", email__role__group__type="area").distinct() seen = [] positions = [] diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py index 02a3b3d33..e277750ff 100644 --- a/ietf/doc/views_charter.py +++ b/ietf/doc/views_charter.py @@ -280,7 +280,7 @@ def change_title(request, name, option=None): context_instance=RequestContext(request)) class AdForm(forms.Form): - ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), + ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active", role__group__type="area").order_by('name'), label="Responsible AD", empty_label="(None)", required=True) def __init__(self, *args, **kwargs): diff --git a/ietf/doc/views_conflict_review.py b/ietf/doc/views_conflict_review.py index b372c0d8c..5f1249ab2 100644 --- a/ietf/doc/views_conflict_review.py +++ b/ietf/doc/views_conflict_review.py @@ -327,7 +327,7 @@ class SimpleStartReviewForm(forms.Form): notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False) class StartReviewForm(forms.Form): - ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), + ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active",role__group__type='area').order_by('name'), label="Shepherding AD", empty_label="(None)", required=True) create_in_state = forms.ModelChoiceField(State.objects.filter(used=True, type="conflrev", slug__in=("needshep", "adrev")), empty_label=None, required=False) notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False) diff --git a/ietf/doc/views_draft.py b/ietf/doc/views_draft.py index ba280b47e..5b147a83e 100644 --- a/ietf/doc/views_draft.py +++ b/ietf/doc/views_draft.py @@ -470,7 +470,7 @@ def change_intention(request, name): class EditInfoForm(forms.Form): intended_std_level = forms.ModelChoiceField(IntendedStdLevelName.objects.filter(used=True), empty_label="(None)", required=True, label="Intended RFC status") area = forms.ModelChoiceField(Group.objects.filter(type="area", state="active"), empty_label="(None - individual submission)", required=False, label="Assigned to area") - ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), label="Responsible AD", empty_label="(None)", required=True) + ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active",role__group__type='area').order_by('name'), label="Responsible AD", empty_label="(None)", required=True) create_in_state = forms.ModelChoiceField(State.objects.filter(used=True, type="draft-iesg", slug__in=("pub-req", "watching")), empty_label=None, required=False) notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False) note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False) @@ -1039,7 +1039,7 @@ def change_shepherd_email(request, name): }) class AdForm(forms.Form): - ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), + ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active", role__group__type="area").order_by('name'), label="Shepherding AD", empty_label="(None)", required=True) def __init__(self, *args, **kwargs): diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py index 4d868b238..1b4b5f2f1 100644 --- a/ietf/doc/views_status_change.py +++ b/ietf/doc/views_status_change.py @@ -438,7 +438,7 @@ class EditStatusChangeForm(forms.Form): class StartStatusChangeForm(forms.Form): document_name = forms.CharField(max_length=255, label="Document name", help_text="A descriptive name such as status-change-md2-to-historic is better than status-change-rfc1319", required=True) title = forms.CharField(max_length=255, label="Title", required=True) - ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), + ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active",role__group__type='area').order_by('name'), label="Shepherding AD", empty_label="(None)", required=True) create_in_state = forms.ModelChoiceField(State.objects.filter(type="statchg", slug__in=("needshep", "adrev")), empty_label=None, required=False) notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False) diff --git a/ietf/group/admin.py b/ietf/group/admin.py index 25a3c42c4..dfd6b342c 100644 --- a/ietf/group/admin.py +++ b/ietf/group/admin.py @@ -26,7 +26,7 @@ class GroupAdmin(admin.ModelAdmin): list_filter = ["type", "state", "time"] search_fields = ["acronym", "name"] ordering = ["name"] - raw_id_fields = ["charter", "parent", "ad"] + raw_id_fields = ["charter", "parent", "_ad"] inlines = [RoleInline, GroupURLInline] prepopulated_fields = {"acronym": ("name", )} @@ -107,7 +107,7 @@ class GroupHistoryAdmin(admin.ModelAdmin): list_filter = ["type"] search_fields = ["acronym", "name"] ordering = ["name"] - raw_id_fields = ["group", "parent", "ad"] + raw_id_fields = ["group", "parent", "_ad"] admin.site.register(GroupHistory, GroupHistoryAdmin) diff --git a/ietf/group/edit.py b/ietf/group/edit.py index 843e46e08..8a815e987 100644 --- a/ietf/group/edit.py +++ b/ietf/group/edit.py @@ -34,7 +34,7 @@ class GroupForm(forms.Form): techadv = AutocompletedEmailsField(label="Technical Advisors", required=False, only_users=True) delegates = AutocompletedEmailsField(required=False, only_users=True, max_entries=MAX_GROUP_DELEGATES, help_text=mark_safe("Chairs can delegate the authority to update the state of group documents - max %s persons at a given time" % MAX_GROUP_DELEGATES)) - ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), label="Shepherding AD", empty_label="(None)", required=False) + ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active", role__group__type='area').order_by('name'), label="Shepherding AD", empty_label="(None)", required=False) parent = forms.ModelChoiceField(Group.objects.filter(state="active").order_by('name'), empty_label="(None)", required=False) list_email = forms.CharField(max_length=64, required=False) list_subscribe = forms.CharField(max_length=255, required=False) diff --git a/ietf/group/migrations/0009_ad_to_role.py b/ietf/group/migrations/0009_ad_to_role.py new file mode 100644 index 000000000..e8f3b65a1 --- /dev/null +++ b/ietf/group/migrations/0009_ad_to_role.py @@ -0,0 +1,309 @@ +# -*- coding: utf-8 -*- +from south.v2 import DataMigration + +class Migration(DataMigration): + + def forwards(self, orm): + rolename=orm['name.RoleName'].objects.get(slug='ad') + for group in orm.Group.objects.exclude(ad=None): + email = None + if group.parent: + ad_rolematch = group.parent.role_set.filter(person=group.ad,name=rolename).first() + if ad_rolematch: + email = ad_rolematch.email + if not email: + email = group.ad.email_set.order_by("-active","-time").first() + group.role_set.get_or_create(name=rolename,person=group.ad,email=email) + + def backwards(self, orm): + pass + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'doc.document': { + 'Meta': {'object_name': 'Document'}, + 'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': u"orm['person.Person']"}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['person.Email']", 'symmetrical': 'False', 'through': u"orm['doc.DocumentAuthor']", 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}), + 'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}), + 'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}), + 'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}), + 'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': u"orm['person.Email']"}), + 'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}), + 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.StreamName']", 'null': 'True', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}) + }, + u'doc.documentauthor': { + 'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '1'}) + }, + u'doc.state': { + 'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': u"orm['doc.State']"}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.StateType']"}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'doc.statetype': { + 'Meta': {'object_name': 'StateType'}, + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}) + }, + u'group.changestategroupevent': { + 'Meta': {'ordering': "['-time', 'id']", 'object_name': 'ChangeStateGroupEvent', '_ormbases': [u'group.GroupEvent']}, + u'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']"}) + }, + u'group.group': { + 'Meta': {'object_name': 'Group'}, + 'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': u"orm['doc.Document']"}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'group.groupevent': { + 'Meta': {'ordering': "['-time', 'id']", 'object_name': 'GroupEvent'}, + 'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}), + 'desc': ('django.db.models.fields.TextField', [], {}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'group.grouphistory': { + 'Meta': {'object_name': 'GroupHistory'}, + 'acronym': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True', 'blank': 'True'}), + 'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupStateName']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupTypeName']", 'null': 'True'}), + 'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}), + 'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'group.groupmilestone': { + 'Meta': {'ordering': "['due', 'id']", 'object_name': 'GroupMilestone'}, + 'desc': ('django.db.models.fields.CharField', [], {'max_length': '500'}), + 'docs': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}), + 'due': ('django.db.models.fields.DateField', [], {}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupMilestoneStateName']"}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'group.groupmilestonehistory': { + 'Meta': {'ordering': "['due', 'id']", 'object_name': 'GroupMilestoneHistory'}, + 'desc': ('django.db.models.fields.CharField', [], {'max_length': '500'}), + 'docs': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['doc.Document']", 'symmetrical': 'False', 'blank': 'True'}), + 'due': ('django.db.models.fields.DateField', [], {}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'milestone': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': u"orm['group.GroupMilestone']"}), + 'resolved': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.GroupMilestoneStateName']"}), + 'time': ('django.db.models.fields.DateTimeField', [], {}) + }, + u'group.groupstatetransitions': { + 'Meta': {'object_name': 'GroupStateTransitions'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_groupstatetransitions_states'", 'symmetrical': 'False', 'to': u"orm['doc.State']"}), + 'state': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['doc.State']"}) + }, + u'group.groupurl': { + 'Meta': {'object_name': 'GroupURL'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + u'group.milestonegroupevent': { + 'Meta': {'ordering': "['-time', 'id']", 'object_name': 'MilestoneGroupEvent', '_ormbases': [u'group.GroupEvent']}, + u'groupevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['group.GroupEvent']", 'unique': 'True', 'primary_key': 'True'}), + 'milestone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.GroupMilestone']"}) + }, + u'group.role': { + 'Meta': {'object_name': 'Role'}, + 'email': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.RoleName']"}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}) + }, + u'group.rolehistory': { + 'Meta': {'object_name': 'RoleHistory'}, + 'email': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Email']"}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['group.GroupHistory']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['name.RoleName']"}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']"}) + }, + u'name.doctagname': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.doctypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.groupmilestonestatename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.groupstatename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.grouptypename': { + 'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.intendedstdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.rolename': { + 'Meta': {'ordering': "['order']", 'object_name': 'RoleName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.stdlevelname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'name.streamname': { + 'Meta': {'ordering': "['order']", 'object_name': 'StreamName'}, + 'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '32', 'primary_key': 'True'}), + 'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + u'person.email': { + 'Meta': {'object_name': 'Email'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}), + 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['person.Person']", 'null': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + u'person.person': { + 'Meta': {'object_name': 'Person'}, + 'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}), + 'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['group'] + symmetrical = True diff --git a/ietf/group/models.py b/ietf/group/models.py index ee372e02b..c9f1967c1 100644 --- a/ietf/group/models.py +++ b/ietf/group/models.py @@ -18,7 +18,7 @@ class GroupInfo(models.Model): type = models.ForeignKey(GroupTypeName, null=True) parent = models.ForeignKey('Group', blank=True, null=True) description = models.TextField(blank=True) - ad = models.ForeignKey(Person, verbose_name="AD", blank=True, null=True) + _ad = models.ForeignKey(Person, verbose_name="AD", blank=True, null=True, db_column="ad_id") list_email = models.CharField(max_length=64, blank=True) list_subscribe = models.CharField(max_length=255, blank=True) list_archive = models.CharField(max_length=255, blank=True) @@ -36,6 +36,21 @@ class GroupInfo(models.Model): res += " %s (%s)" % (self.type, self.acronym) return res + @property + def ad(self): + ad_role = self.role_set.filter(name__slug='ad').first() + return ad_role and ad_role.person + + @ad.setter + def ad(self,value): + self.role_set.filter(name__slug='ad').delete() + if value: + self.role_set.create(name=RoleName.objects.get(slug='ad'), person=value, email=value.role_email('ad')) + + @property + def ad_id(self): + return self.ad.id + @property def features(self): if not hasattr(self, "features_cache"): diff --git a/ietf/iesg/views.py b/ietf/iesg/views.py index cd7b155d0..25ec44aa9 100644 --- a/ietf/iesg/views.py +++ b/ietf/iesg/views.py @@ -250,7 +250,7 @@ def agenda_moderator_package(request, date=None): flattened_sections.append((num, s)) # add ads - data["sections"]["7"]["ads"] = sorted(Person.objects.filter(role__name="ad", role__group__state="active"), + data["sections"]["7"]["ads"] = sorted(Person.objects.filter(role__name="ad", role__group__state="active", role__group__type="area"), key=lambda p: p.name_parts()[3]) return render_to_response("iesg/moderator_package.html", { @@ -445,10 +445,11 @@ def discusses(request): def milestones_needing_review(request): # collect milestones, grouped on AD and group ads = {} - for m in GroupMilestone.objects.filter(state="review").exclude(group__state="concluded").exclude(group__ad=None).distinct().select_related("group", "group__ad"): - groups = ads.setdefault(m.group.ad, {}) - milestones = groups.setdefault(m.group, []) - milestones.append(m) + for m in GroupMilestone.objects.filter(state="review").exclude(group__state="concluded").distinct().select_related("group"): + if m.group.ad: + groups = ads.setdefault(m.group.ad, {}) + milestones = groups.setdefault(m.group, []) + milestones.append(m) ad_list = [] for ad, groups in ads.iteritems(): diff --git a/ietf/secr/groups/forms.py b/ietf/secr/groups/forms.py index 075deedc4..01b5a19a7 100644 --- a/ietf/secr/groups/forms.py +++ b/ietf/secr/groups/forms.py @@ -67,7 +67,7 @@ class GroupMilestoneForm(forms.ModelForm): class GroupModelForm(forms.ModelForm): type = forms.ModelChoiceField(queryset=GroupTypeName.objects.all(),empty_label=None) parent = forms.ModelChoiceField(queryset=Group.objects.filter(Q(type='area',state='active')|Q(acronym='irtf')),required=False) - ad = forms.ModelChoiceField(queryset=Person.objects.filter(role__name='ad',role__group__state='active'),required=False) + ad = forms.ModelChoiceField(queryset=Person.objects.filter(role__name='ad',role__group__state='active',role__group__type='area'),required=False) state = forms.ModelChoiceField(queryset=GroupStateName.objects.exclude(slug__in=('dormant','unknown')),empty_label=None) class Meta: diff --git a/ietf/secr/telechat/views.py b/ietf/secr/telechat/views.py index 1440052b3..c3f2be7df 100644 --- a/ietf/secr/telechat/views.py +++ b/ietf/secr/telechat/views.py @@ -396,7 +396,7 @@ def new(request): @role_required('Secretariat') def roll_call(request, date): agenda = agenda_data(date=date) - ads = Person.objects.filter(role__name='ad', role__group__state="active") + ads = Person.objects.filter(role__name='ad', role__group__state="active",role__group__type="area") sorted_ads = sorted(ads, key = lambda a: a.name_parts()[3]) return render_to_response('telechat/roll_call.html', {