908 lines
36 KiB
Python
908 lines
36 KiB
Python
# 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
|