# Copyright The IETF Trust 2007, All Rights Reserved from django.db import models from ietf.utils import FKAsOneToOne class Acronym(models.Model): acronym_id = models.AutoField(primary_key=True) acronym = models.CharField(maxlength=12) name = models.CharField(maxlength=100) name_key = models.CharField(maxlength=50, editable=False) def save(self): self.name_key = self.name.upper() super(Acronym, self).save() def __str__(self): return self.acronym class Meta: db_table = "acronym" class Admin: list_display = ('acronym', 'name') pass class AreaStatus(models.Model): status_id = models.AutoField(primary_key=True) status = models.CharField(maxlength=25, db_column='status_value') def __str__(self): return self.status class Meta: db_table = 'area_status' class Admin: pass # I think equiv_group_flag is historical. class IDState(models.Model): document_state_id = models.AutoField(primary_key=True) state = models.CharField(maxlength=50, db_column='document_state_val') equiv_group_flag = models.IntegerField(null=True, blank=True) description = models.TextField(blank=True, db_column='document_desc') def __str__(self): return self.state def choices(): return [(state.document_state_id, state.state) for state in IDState.objects.all()] choices = staticmethod(choices) class Meta: db_table = 'ref_doc_states_new' ordering = ['document_state_id'] class Admin: pass class IDNextState(models.Model): cur_state = models.ForeignKey(IDState, related_name='nextstate') next_state = models.ForeignKey(IDState, related_name='prevstate', core=True) condition = models.CharField(blank=True, maxlength=255) def __str__(self): return "%s -> %s" % (self.cur_state.state, self.next_state.state ) class Meta: db_table = 'ref_next_states_new' class Admin: pass class IDSubState(models.Model): sub_state_id = models.AutoField(primary_key=True) sub_state = models.CharField(maxlength=55, db_column='sub_state_val') description = models.TextField(blank=True, db_column='sub_state_desc') def __str__(self): return self.sub_state class Meta: db_table = 'sub_state' ordering = ['sub_state_id'] class Admin: pass class Area(models.Model): ACTIVE=1 area_acronym = models.ForeignKey(Acronym, primary_key=True, unique=True) start_date = models.DateField(auto_now_add=True) concluded_date = models.DateField(null=True, blank=True) status = models.ForeignKey(AreaStatus) comments = models.TextField(blank=True) last_modified_date = models.DateField(auto_now=True) extra_email_addresses = models.TextField(blank=True) def __str__(self): return self.area_acronym.acronym def active_area_choices(): return [(area.area_acronym_id, area.area_acronym.acronym) for area in Area.objects.filter(status=1).select_related().order_by('acronym.acronym')] active_area_choices = staticmethod(active_area_choices) class Meta: db_table = 'areas' verbose_name="area" class Admin: list_display = ('area_acronym', 'status') pass class IDStatus(models.Model): status_id = models.AutoField(primary_key=True) status = models.CharField(maxlength=25, db_column='status_value') def __str__(self): return self.status class Meta: db_table = "id_status" verbose_name="I-D Status" verbose_name_plural="I-D Statuses" class Admin: pass class IDIntendedStatus(models.Model): intended_status_id = models.AutoField(primary_key=True) intended_status = models.CharField(maxlength=25, db_column='status_value') def __str__(self): return self.intended_status class Meta: db_table = "id_intended_status" verbose_name="I-D Intended Publication Status" verbose_name_plural="I-D Intended Publication Statuses" class Admin: pass class InternetDraft(models.Model): id_document_tag = models.AutoField(primary_key=True) title = models.CharField(maxlength=255, db_column='id_document_name') id_document_key = models.CharField(maxlength=255, editable=False) group = models.ForeignKey(Acronym, db_column='group_acronym_id') filename = models.CharField(maxlength=255, unique=True) revision = models.CharField(maxlength=2) revision_date = models.DateField() file_type = models.CharField(maxlength=20) txt_page_count = models.IntegerField() local_path = models.CharField(maxlength=255, blank=True) start_date = models.DateField() expiration_date = models.DateField() abstract = models.TextField() dunn_sent_date = models.DateField() extension_date = models.DateField(null=True, blank=True) status = models.ForeignKey(IDStatus) intended_status = models.ForeignKey(IDIntendedStatus) lc_sent_date = models.DateField(null=True, blank=True) lc_changes = models.CharField(maxlength=3) lc_expiration_date = models.DateField(null=True, blank=True) b_sent_date = models.DateField(null=True, blank=True) b_discussion_date = models.DateField(null=True, blank=True) b_approve_date = models.DateField(null=True, blank=True) wgreturn_date = models.DateField(null=True, blank=True) rfc_number = models.IntegerField(null=True, blank=True) comments = models.TextField(blank=True) last_modified_date = models.DateField() replaced_by = models.ForeignKey('self', db_column='replaced_by', raw_id_admin=True, blank=True, null=True, related_name='replaces_set') replaces = FKAsOneToOne('replaces', reverse=True) review_by_rfc_editor = models.BooleanField() expired_tombstone = models.BooleanField() idinternal = FKAsOneToOne('idinternal', reverse=True, query=models.Q(rfc_flag = 0)) def save(self): self.id_document_key = self.title.upper() super(InternetDraft, self).save() def displayname(self): return "%s-%s.txt" % ( self.filename, self.revision_display() ) def doclink(self): return "http://www.ietf.org/internet-drafts/%s" % ( self.displayname() ) def group_acronym(self): return self.group.acronym def __str__(self): return self.filename def idstate(self): idinternal = self.idinternal if idinternal: return idinternal.docstate() else: return "I-D Exists" def revision_display(self): r = int(self.revision) if self.status.status != 'Active' and not self.expired_tombstone: r = max(r - 1, 0) return "%02d" % r def doctype(self): return "Draft" def filename_with_link(self, text=None): if text is None: text=self.filename if self.status.status != 'Active': return text else: return '<a href="%s">%s</a>' % ( self.doclink(), text ) def displayname_with_link(self): return self.filename_with_link(self.displayname()) class Meta: db_table = "internet_drafts" class Admin: search_fields = ['filename'] list_display = ('filename', 'revision', 'status') list_filter = ['status'] pass #date_hierarchy = 'revision_date' #list_filter = ['revision_date'] class PersonOrOrgInfo(models.Model): person_or_org_tag = models.AutoField(primary_key=True) record_type = models.CharField(blank=True, maxlength=8) name_prefix = models.CharField(blank=True, maxlength=10) first_name = models.CharField(blank=True, maxlength=20) first_name_key = models.CharField(blank=True, maxlength=20, editable=False) middle_initial = models.CharField(blank=True, maxlength=4) middle_initial_key = models.CharField(blank=True, maxlength=4, editable=False) last_name = models.CharField(blank=True, maxlength=50) last_name_key = models.CharField(blank=True, maxlength=50, editable=False) name_suffix = models.CharField(blank=True, maxlength=10) date_modified = models.DateField(null=True, blank=True, auto_now=True) modified_by = models.CharField(blank=True, maxlength=8) date_created = models.DateField(auto_now_add=True) created_by = models.CharField(blank=True, maxlength=8) address_type = models.CharField(blank=True, maxlength=4) def save(self): self.first_name_key = self.first_name.upper() self.middle_initial_key = self.middle_initial.upper() self.last_name_key = self.last_name.upper() super(PersonOrOrgInfo, self).save() def __str__(self): if self.first_name == '' and self.last_name == '': return self.affiliation() return "%s %s" % ( self.first_name or "<nofirst>", self.last_name or "<nolast>") def email(self, priority=1, type='INET'): name = str(self) try: email = self.emailaddress_set.get(priority=priority, type=type).address except EmailAddress.DoesNotExist: email = '' return (name, email) # Added by Sunny Lee to display person's affiliation - 5/26/2007 def affiliation(self, priority=1): try: postal = self.postaladdress_set.get(address_priority=priority) except PostalAddress.DoesNotExist: return "PersonOrOrgInfo with no postal address!" except AssertionError: return "PersonOrOrgInfo with multiple priority-%d addresses!" % priority return "%s" % ( postal.affiliated_company or postal.department or "???" ) class Meta: db_table = 'person_or_org_info' ordering = ['last_name'] verbose_name="Rolodex Entry" verbose_name_plural="Rolodex" class Admin: search_fields = ['first_name','last_name'] pass # could use a mapping for user_level class IESGLogin(models.Model): USER_LEVEL_CHOICES = ( ('0', 'Secretariat'), ('1', 'IESG'), ('2', 'ex-IESG'), ('3', 'Level 3'), ('4', 'Comment Only(?)'), ) id = models.AutoField(primary_key=True) login_name = models.CharField(blank=True, maxlength=255) password = models.CharField(maxlength=25) user_level = models.IntegerField(choices=USER_LEVEL_CHOICES) first_name = models.CharField(blank=True, maxlength=25) last_name = models.CharField(blank=True, maxlength=25) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, unique=True) pgp_id = models.CharField(blank=True, maxlength=20) default_search = models.IntegerField(null=True) def __str__(self): #return "%s, %s" % ( self.last_name, self.first_name) return "%s %s" % ( self.first_name, self.last_name) def is_current_ad(self): return self.user_level == 1 def active_iesg(): return IESGLogin.objects.filter(user_level=1,id__gt=1).order_by('last_name') #XXX hardcoded active_iesg = staticmethod(active_iesg) class Meta: db_table = 'iesg_login' class Admin: list_display = ('login_name', 'first_name', 'last_name', 'user_level') ordering = ['user_level','last_name'] pass class AreaDirector(models.Model): area = models.ForeignKey(Area, db_column='area_acronym_id', edit_inline=models.STACKED, num_in_admin=2, null=True) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, core=True) def __str__(self): return "%s (%s)" % ( self.person, self.role() ) def role(self): try: return "%s AD" % self.area except Area.DoesNotExist: return "?%d? AD" % self.area_id class Meta: db_table = 'area_directors' class Admin: pass ### # RFC tables class RfcIntendedStatus(models.Model): intended_status_id = models.AutoField(primary_key=True) status = models.CharField(maxlength=25, db_column='status_value') def __str__(self): return self.status class Meta: db_table = 'rfc_intend_status' verbose_name = 'RFC Intended Status Field' class Admin: pass class RfcStatus(models.Model): status_id = models.AutoField(primary_key=True) status = models.CharField(maxlength=25, db_column='status_value') def __str__(self): return self.status class Meta: db_table = 'rfc_status' verbose_name = 'RFC Status' verbose_name_plural = 'RFC Statuses' class Admin: pass class Rfc(models.Model): rfc_number = models.IntegerField(primary_key=True) title = models.CharField(maxlength=200, db_column='rfc_name') rfc_name_key = models.CharField(maxlength=200, editable=False) group_acronym = models.CharField(blank=True, maxlength=8) area_acronym = models.CharField(blank=True, maxlength=8) status = models.ForeignKey(RfcStatus, db_column="status_id") intended_status = models.ForeignKey(RfcIntendedStatus, db_column="intended_status_id") fyi_number = models.CharField(blank=True, maxlength=20) std_number = models.CharField(blank=True, maxlength=20) txt_page_count = models.IntegerField(null=True, blank=True) online_version = models.CharField(blank=True, maxlength=3) rfc_published_date = models.DateField(null=True, blank=True) proposed_date = models.DateField(null=True, blank=True) draft_date = models.DateField(null=True, blank=True) standard_date = models.DateField(null=True, blank=True) historic_date = models.DateField(null=True, blank=True) lc_sent_date = models.DateField(null=True, blank=True) lc_expiration_date = models.DateField(null=True, blank=True) b_sent_date = models.DateField(null=True, blank=True) b_approve_date = models.DateField(null=True, blank=True) comments = models.TextField(blank=True) last_modified_date = models.DateField() def __str__(self): return "RFC%04d" % ( self.rfc_number ) def save(self): self.rfc_name_key = self.title.upper() super(Rfc, self).save() def displayname(self): return "%s.txt" % ( self.filename() ) def filename(self): return "rfc%d" % ( self.rfc_number ) def revision(self): return "RFC" def revision_display(self): return "RFC" def doclink(self): return "http://www.ietf.org/rfc/%s" % ( self.displayname() ) def doctype(self): return "RFC" def filename_with_link(self): return '<a href="%s">%s</a>' % ( self.doclink(), self.displayname() ) def displayname_with_link(self): return self.filename_with_link() _idinternal_cache = None _idinternal_cached = False def idinternal(self): if self._idinternal_cached: return self._idinternal_cache try: self._idinternal_cache = IDInternal.objects.get(draft=self.rfc_number, rfc_flag=1) except IDInternal.DoesNotExist: self._idinternal_cache = None self._idinternal_cached = True return self._idinternal_cache class Meta: db_table = 'rfcs' verbose_name = 'RFC' verbose_name_plural = 'RFCs' class Admin: search_fields = ['title', 'group', 'area'] list_display = ['rfc_number', 'title'] pass class RfcAuthor(models.Model): rfc = models.ForeignKey(Rfc, unique=True, db_column='rfc_number', related_name='authors', edit_inline=models.TABULAR) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, core=True) def __str__(self): return "%s, %s" % ( self.person.last_name, self.person.first_name) class Meta: db_table = 'rfc_authors' verbose_name = 'RFC Author' class RfcObsolete(models.Model): rfc = models.ForeignKey(Rfc, db_column='rfc_number', raw_id_admin=True, related_name='updates_or_obsoletes') action = models.CharField(maxlength=20, core=True) rfc_acted_on = models.ForeignKey(Rfc, db_column='rfc_acted_on', raw_id_admin=True, related_name='updated_or_obsoleted_by') def __str__(self): return "RFC%04d %s RFC%04d" % (self.rfc_id, self.action, self.rfc_acted_on_id) class Meta: db_table = 'rfcs_obsolete' verbose_name = 'RFC updates or obsoletes' verbose_name_plural = verbose_name class Admin: pass ## End RFC Tables class BallotInfo(models.Model): # Added by Michael Lee ballot = models.AutoField(primary_key=True, db_column='ballot_id') active = models.BooleanField() an_sent = models.BooleanField() an_sent_date = models.DateField(null=True, blank=True) an_sent_by = models.ForeignKey(IESGLogin, db_column='an_sent_by', related_name='ansent') defer = models.BooleanField(null=True, blank=True) defer_by = models.ForeignKey(IESGLogin, db_column='defer_by', related_name='deferred') defer_date = models.DateField(null=True, blank=True) approval_text = models.TextField(blank=True) last_call_text = models.TextField(blank=True) ballot_writeup = models.TextField(blank=True) ballot_issued = models.IntegerField(null=True, blank=True) def __str__(self): try: return "Ballot for %s" % self.drafts.filter(primary_flag=1) except IDInternal.DoesNotExist: return "Ballot ID %d (no I-D?)" % (self.ballot) def remarks(self): remarks = list(self.discusses.all()) + list(self.comments.all()) return remarks def active_positions(self): '''Returns a list of dicts, with AD and Position tuples''' active_iesg = IESGLogin.active_iesg() ads = [ad.id for ad in active_iesg] positions = {} for position in self.positions.filter(ad__in=ads): positions[position.ad_id] = position ret = [] for ad in active_iesg: ret.append({'ad': ad, 'pos': positions.get(ad.id, None)}) return ret class Meta: db_table = 'ballot_info' class Admin: pass class IDInternal(models.Model): """ An IDInternal represents a document that has been added to the I-D tracker. It can be either an Internet Draft or an RFC. The table has only a single primary key field, meaning that there is the danger of RFC number collision with low-numbered Internet Drafts. Since it's most common to be an Internet Draft, the draft field is defined as a FK to InternetDrafts. One side effect of this is that select_related() will only work with rfc_flag=0. When searching where matches may be either I-Ds or RFCs, you cannot use draft__ as that will cause an INNER JOIN which will limit the responses to I-Ds. """ draft = models.ForeignKey(InternetDraft, primary_key=True, unique=True, db_column='id_document_tag') rfc_flag = models.IntegerField(null=True) ballot = models.ForeignKey(BallotInfo, related_name='drafts', db_column="ballot_id") primary_flag = models.IntegerField(blank=True, null=True) group_flag = models.IntegerField(blank=True) token_name = models.CharField(blank=True, maxlength=25) token_email = models.CharField(blank=True, maxlength=255) note = models.TextField(blank=True) status_date = models.DateField(null=True) email_display = models.CharField(blank=True, maxlength=50) agenda = models.IntegerField(null=True, blank=True) cur_state = models.ForeignKey(IDState, db_column='cur_state', related_name='docs') prev_state = models.ForeignKey(IDState, db_column='prev_state', related_name='docs_prev') assigned_to = models.CharField(blank=True, maxlength=25) mark_by = models.ForeignKey(IESGLogin, db_column='mark_by', related_name='marked') job_owner = models.ForeignKey(IESGLogin, db_column='job_owner', related_name='documents') event_date = models.DateField(null=True) area_acronym = models.ForeignKey(Area) cur_sub_state = models.ForeignKey(IDSubState, related_name='docs', null=True, blank=True) prev_sub_state = models.ForeignKey(IDSubState, related_name='docs_prev', null=True, blank=True) returning_item = models.IntegerField(null=True, blank=True) telechat_date = models.DateField(null=True, blank=True) via_rfc_editor = models.IntegerField(null=True, blank=True) state_change_notice_to = models.CharField(blank=True, maxlength=255) dnp = models.IntegerField(null=True, blank=True) dnp_date = models.DateField(null=True, blank=True) noproblem = models.IntegerField(null=True, blank=True) resurrect_requested_by = models.ForeignKey(IESGLogin, db_column='resurrect_requested_by', related_name='docsresurrected', null=True, blank=True) approved_in_minute = models.IntegerField(null=True, blank=True) def __str__(self): if self.rfc_flag: return "RFC%04d" % ( self.draft_id ) else: return self.draft.filename def get_absolute_url(self): if self.rfc_flag: return "/idtracker/rfc%d/" % ( self.draft_id ) else: return "/idtracker/%s/" % ( self.draft.filename ) _cached_rfc = None def document(self): if self.rfc_flag: if self._cached_rfc is None: self._cached_rfc = Rfc.objects.get(rfc_number=self.draft_id) return self._cached_rfc else: return self.draft def public_comments(self): return self.comments().filter(public_flag=1) def comments(self): # would filter by rfc_flag but the database is broken. (see # trac ticket #96) so this risks collisions. return self.documentcomment_set.all().order_by('-comment_date','-comment_time','-id') def ballot_set(self): return IDInternal.objects.filter(ballot=self.ballot_id).order_by('-primary_flag') def ballot_primary(self): return IDInternal.objects.filter(ballot=self.ballot_id,primary_flag=1) def ballot_others(self): return IDInternal.objects.filter(models.Q(primary_flag=0)|models.Q(primary_flag__isnull=True), ballot=self.ballot_id) def docstate(self): if self.cur_sub_state_id > 0: return "%s :: %s" % ( self.cur_state, self.cur_sub_state ) else: return self.cur_state class Meta: db_table = 'id_internal' verbose_name = 'IDTracker Draft' class Admin: pass class DocumentComment(models.Model): BALLOT_CHOICES = ( (1, 'discuss'), (2, 'comment'), ) document = models.ForeignKey(IDInternal) rfc_flag = models.IntegerField(null=True, blank=True) public_flag = models.IntegerField() date = models.DateField(db_column='comment_date') time = models.CharField(db_column='comment_time', maxlength=20) version = models.CharField(blank=True, maxlength=3) comment_text = models.TextField(blank=True) created_by = models.ForeignKey(IESGLogin, db_column='created_by', null=True) result_state = models.ForeignKey(IDState, db_column='result_state', null=True, related_name="comments_leading_to_state") origin_state = models.ForeignKey(IDState, db_column='origin_state', null=True, related_name="comments_coming_from_state") ballot = models.IntegerField(null=True, choices=BALLOT_CHOICES) def get_absolute_url(self): if self.rfc_flag: return "/idtracker/rfc%d/comment/%d/" % (self.document_id, self.id) else: return "/idtracker/%s/comment/%d/" % (self.document.draft.filename, self.id) def get_author(self): if self.created_by_id and self.created_by_id != 999: return self.created_by.__str__() else: return "system" def get_username(self): if self.created_by_id and self.created_by_id != 999: return self.created_by.login_name else: return "system" class Meta: db_table = 'document_comments' class Position(models.Model): ballot = models.ForeignKey(BallotInfo, raw_id_admin=True, related_name='positions') ad = models.ForeignKey(IESGLogin, raw_id_admin=True) yes = models.IntegerField(db_column='yes_col') noobj = models.IntegerField(db_column='no_col') abstain = models.IntegerField() approve = models.IntegerField() discuss = models.IntegerField() recuse = models.IntegerField() def __str__(self): return "Position for %s on %s" % ( self.ad, self.ballot ) def abstain_ind(self): if self.recuse: return 'R' if self.abstain: return 'X' else: return ' ' class Meta: db_table = 'ballots' unique_together = (('ballot', 'ad'), ) verbose_name = "IESG Ballot Position" class Admin: pass class IESGComment(models.Model): ballot = models.ForeignKey(BallotInfo, raw_id_admin=True, related_name="comments") ad = models.ForeignKey(IESGLogin, raw_id_admin=True) date = models.DateField(db_column="comment_date") revision = models.CharField(maxlength=2) active = models.IntegerField() text = models.TextField(blank=True, db_column="comment_text") def __str__(self): return "Comment text by %s on %s" % ( self.ad, self.ballot ) def is_comment(self): return True class Meta: db_table = 'ballots_comment' unique_together = (('ballot', 'ad'), ) verbose_name = 'IESG Comment Text' verbose_name_plural = 'IESG Comments' class Admin: pass class IESGDiscuss(models.Model): ballot = models.ForeignKey(BallotInfo, raw_id_admin=True, related_name="discusses") ad = models.ForeignKey(IESGLogin, raw_id_admin=True) date = models.DateField(db_column="discuss_date") revision = models.CharField(maxlength=2) active = models.IntegerField() text = models.TextField(blank=True, db_column="discuss_text") def __str__(self): return "Discuss text by %s on %s" % ( self.ad, self.ballot ) def is_discuss(self): return True class Meta: db_table = 'ballots_discuss' unique_together = (('ballot', 'ad'), ) verbose_name = 'IESG Discuss Text' verbose_name_plural = 'IESG Discusses' class Admin: pass class IDAuthor(models.Model): document = models.ForeignKey(InternetDraft, db_column='id_document_tag', related_name='authors', edit_inline=models.TABULAR, raw_id_admin=True) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, core=True) author_order = models.IntegerField(null=True, blank=True) def __str__(self): return "%s authors %s" % ( self.person, self.document.filename ) def email(self): try: return self.person.emailaddress_set.filter(type='I-D').get(priority=self.document_id).address except EmailAddress.DoesNotExist: return None class Meta: db_table = 'id_authors' verbose_name = "I-D Author" ordering = ['document','author_order'] # PostalAddress, EmailAddress and PhoneNumber are edited in # the admin for the Rolodex. # The unique_together constraint is commented out for now, because # of a bug in oldforms and AutomaticManipulator which fails to # create the isUniquefoo_bar method properly. Since django is # moving away from oldforms, I have to assume that this is going # to be fixed by moving admin to newforms. # A table without a unique primary key! # must decide which field is/are core. class PostalAddress(models.Model): address_type = models.CharField(maxlength=4) address_priority = models.IntegerField(null=True) person_or_org = models.ForeignKey(PersonOrOrgInfo, primary_key=True, db_column='person_or_org_tag', edit_inline=models.STACKED) person_title = models.CharField(maxlength=50, blank=True) affiliated_company = models.CharField(maxlength=70, blank=True) aff_company_key = models.CharField(maxlength=70, blank=True, editable=False) department = models.CharField(maxlength=100, blank=True) staddr1 = models.CharField(maxlength=40, core=True) staddr2 = models.CharField(maxlength=40, blank=True) mail_stop = models.CharField(maxlength=20, blank=True) city = models.CharField(maxlength=20, blank=True) state_or_prov = models.CharField(maxlength=20, blank=True) postal_code = models.CharField(maxlength=20, blank=True) country = models.CharField(maxlength=20, blank=True) def save(self): self.aff_company_key = self.affiliated_company.upper() super(PostalAddress, self).save() class Meta: db_table = 'postal_addresses' #unique_together = (('address_type', 'person_or_org'), ) verbose_name_plural = 'Postal Addresses' class EmailAddress(models.Model): person_or_org = models.ForeignKey(PersonOrOrgInfo, primary_key=True, db_column='person_or_org_tag', edit_inline=models.TABULAR) type = models.CharField(maxlength=12, db_column='email_type') priority = models.IntegerField(db_column='email_priority') address = models.CharField(maxlength=255, core=True, db_column='email_address') comment = models.CharField(blank=True, maxlength=255, db_column='email_comment') def __str__(self): return self.address class Meta: db_table = 'email_addresses' #unique_together = (('email_priority', 'person_or_org'), ) # with this, I get 'ChangeManipulator' object has no attribute 'isUniqueemail_priority_person_or_org' class PhoneNumber(models.Model): person_or_org = models.ForeignKey(PersonOrOrgInfo, primary_key=True, db_column='person_or_org_tag', edit_inline=models.TABULAR) phone_type = models.CharField(maxlength=3) phone_priority = models.IntegerField() phone_number = models.CharField(blank=True, maxlength=255, core=True) phone_comment = models.CharField(blank=True, maxlength=255) class Meta: db_table = 'phone_numbers' #unique_together = (('phone_priority', 'person_or_org'), ) ### Working Groups class WGType(models.Model): group_type_id = models.AutoField(primary_key=True) type = models.CharField(maxlength=25, db_column='group_type') def __str__(self): return self.type class Meta: db_table = 'g_type' class Admin: pass class WGStatus(models.Model): status_id = models.AutoField(primary_key=True) status = models.CharField(maxlength=25, db_column='status_value') def __str__(self): return self.status class Meta: db_table = 'g_status' class Admin: pass class IETFWG(models.Model): ACTIVE = 1 group_acronym = models.ForeignKey(Acronym, primary_key=True, unique=True, editable=False) group_type = models.ForeignKey(WGType) proposed_date = models.DateField(null=True, blank=True) start_date = models.DateField(null=True, blank=True) dormant_date = models.DateField(null=True, blank=True) concluded_date = models.DateField(null=True, blank=True) status = models.ForeignKey(WGStatus) area_director = models.ForeignKey(AreaDirector, null=True) meeting_scheduled = models.CharField(blank=True, maxlength=3) email_address = models.CharField(blank=True, maxlength=60) email_subscribe = models.CharField(blank=True, maxlength=120) email_keyword = models.CharField(blank=True, maxlength=50) email_archive = models.CharField(blank=True, maxlength=95) comments = models.TextField(blank=True) last_modified_date = models.DateField() meeting_scheduled_old = models.CharField(blank=True, maxlength=3) area = FKAsOneToOne('areagroup', reverse=True) def __str__(self): return self.group_acronym.acronym def active_drafts(self): return self.group_acronym.internetdraft_set.all().filter(status__status="Active") def choices(): return [(wg.group_acronym_id, wg.group_acronym.acronym) for wg in IETFWG.objects.all().filter(group_type__type='WG').select_related().order_by('acronym.acronym')] choices = staticmethod(choices) def area_acronym(self): return AreaGroup.objects.filter(group_acronym_id=self.group_acronym_id).area class Meta: db_table = 'groups_ietf' ordering = ['?'] # workaround django wanting to sort by acronym but not joining with it verbose_name = 'IETF Working Group' class Admin: search_fields = ['group_acronym__acronym', 'group_acronym__name'] list_display = ('group_acronym', 'group_type', 'status', 'area_director') list_filter = ['status', 'group_type', 'area_director'] pass class WGChair(models.Model): person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, unique=True, core=True) group_acronym = models.ForeignKey(IETFWG, edit_inline=models.TABULAR) def __str__(self): return "%s (%s)" % ( self.person, self.role() ) def role(self): return "%s %s Chair" % ( self.group_acronym.acronym, self.group_acronym.group_type ) class Meta: db_table = 'g_chairs' verbose_name = "WG Chair" class WGEditor(models.Model): group_acronym = models.ForeignKey(IETFWG, edit_inline=models.TABULAR) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, unique=True, core=True) class Meta: db_table = 'g_editors' verbose_name = "WG Editor" # Note: there is an empty table 'g_secretary'. # This uses the 'g_secretaries' table but is called 'GSecretary' to # match the model naming scheme. class WGSecretary(models.Model): group_acronym = models.ForeignKey(IETFWG, edit_inline=models.TABULAR) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, unique=True, core=True) def __str__(self): return "%s (%s)" % ( self.person, self.role() ) def role(self): return "%s %s Secretary" % ( self.group_acronym.acronym, self.group_acronym.group_type ) class Meta: db_table = 'g_secretaries' verbose_name = "WG Secretary" verbose_name_plural = "WG Secretaries" class WGTechAdvisor(models.Model): group_acronym = models.ForeignKey(IETFWG, edit_inline=models.TABULAR) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True, core=True) def __str__(self): return "%s (%s)" % ( self.person, self.role() ) def role(self): return "%s Technical Advisor" % self.group_acronym.acronym class Meta: db_table = 'g_tech_advisors' verbose_name = "WG Technical Advisor" class AreaGroup(models.Model): area = models.ForeignKey(Area, db_column='area_acronym_id', related_name='areagroup', core=True) group = models.ForeignKey(IETFWG, db_column='group_acronym_id', edit_inline=models.TABULAR, num_in_admin=1, max_num_in_admin=1, unique=True) def __str__(self): return "%s is in %s" % ( self.group, self.area ) class Meta: db_table = 'area_group' verbose_name = 'Area this group is in' verbose_name_plural = 'Area to Group mappings' class GoalMilestone(models.Model): DONE_CHOICES = ( ('Done', 'Done'), ('No', 'Not Done'), ) gm_id = models.AutoField(primary_key=True) group_acronym = models.ForeignKey(IETFWG, raw_id_admin=True) description = models.TextField() expected_due_date = models.DateField() done_date = models.DateField(null=True, blank=True) done = models.CharField(blank=True, choices=DONE_CHOICES, maxlength=4) last_modified_date = models.DateField() def __str__(self): return self.description class Meta: db_table = 'goals_milestones' verbose_name = 'IETF WG Goal or Milestone' verbose_name_plural = 'IETF WG Goals or Milestones' ordering = ['expected_due_date'] class Admin: list_display = ('group_acronym', 'description', 'expected_due_date', 'done') date_hierarchy = 'expected_due_date' list_filter = ['done'] pass #### end wg stuff class Role(models.Model): '''This table is named 'chairs' in the database, as its original role was to store "who are IETF, IAB and IRTF chairs?". It has since expanded to store roles, such as "IAB Exec Dir" and "IAD", so the model is renamed. ''' person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True) role_name = models.CharField(maxlength=25, db_column='chair_name') def __str__(self): return "%s (%s)" % (self.person, self.role()) def role(self): if self.role_name in ('IETF', 'IAB', 'IRTF', 'NomCom'): return "%s Chair" % self.role_name else: return self.role_name class Meta: db_table = 'chairs' class Admin: pass class ChairsHistory(models.Model): CHAIR_CHOICES = ( ( '1', 'IETF' ), ( '2', 'IAB' ), ( '3', 'NOMCOM' ), ) chair_type_id = models.IntegerField(choices=CHAIR_CHOICES) present_chair = models.BooleanField() person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True) start_year = models.IntegerField() end_year = models.IntegerField(null=True, blank=True) class Meta: db_table = 'chairs_history' # # IRTF RG info class IRTF(models.Model): irtf_id = models.AutoField(primary_key=True) acronym = models.CharField(blank=True, maxlength=25, db_column='irtf_acronym') name = models.CharField(blank=True, maxlength=255, db_column='irtf_name') charter_text = models.TextField(blank=True) meeting_scheduled = models.BooleanField(null=True, blank=True) class Meta: db_table = 'irtf' class Admin: pass class IRTFChair(models.Model): irtf = models.ForeignKey(IRTF) person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', raw_id_admin=True) class Meta: db_table = 'irtf_chairs' class Admin: pass # Not a model, but it's related. # This is used in the view to represent documents # in "I-D Exists". # class DocumentWrapper(object): '''A wrapper for a document, used to synthesize I-D Exists.''' document = None synthetic = True job_owner = "Not Assigned Yet" docstate = "I-D Exists" cur_state = "I-D Exists" cur_state_id = 100 primary_flag = 1 def __init__(self, document): self.document = document