Fix some problems with liaison importer and related models, add a
test, port account management and related utilities, fix up proxy and port most of the views and form code - Legacy-Id: 3345
This commit is contained in:
parent
24488a957b
commit
91ced5c24a
|
@ -42,10 +42,10 @@ from django.conf import settings
|
|||
from pyquery import PyQuery
|
||||
|
||||
from ietf.idtracker.models import IDDates
|
||||
from doc.models import *
|
||||
from name.models import *
|
||||
from group.models import *
|
||||
from person.models import *
|
||||
from redesign.doc.models import *
|
||||
from redesign.name.models import *
|
||||
from redesign.group.models import *
|
||||
from redesign.person.models import *
|
||||
from ietf.iesg.models import TelechatDates
|
||||
from ietf.utils.test_utils import SimpleUrlTestCase, RealDatabaseTest, login_testing_unauthorized
|
||||
from ietf.utils.test_runner import mail_outbox
|
||||
|
|
|
@ -2,7 +2,7 @@ from redesign.person.models import Person
|
|||
from redesign.group.models import Role
|
||||
|
||||
|
||||
LIAISON_EDIT_GROUPS = ['Secretariat']
|
||||
LIAISON_EDIT_GROUPS = ['Secretariat'] # this is not working anymore, refers to old auth model
|
||||
|
||||
|
||||
def get_ietf_chair():
|
||||
|
@ -31,7 +31,10 @@ def get_iab_executive_director():
|
|||
|
||||
|
||||
def get_person_for_user(user):
|
||||
return user.get_profile()
|
||||
p = user.get_profile()
|
||||
p.email = lambda: (p.name, p.email_address().address)
|
||||
|
||||
return p
|
||||
|
||||
|
||||
def is_areadirector(person):
|
||||
|
@ -80,7 +83,7 @@ def is_sdo_authorized_individual(person):
|
|||
|
||||
|
||||
def is_secretariat(user):
|
||||
return bool(Role.objects.filter(email__person=user.get_profile(), name="auth", group__acronym="secretariat"))
|
||||
return bool(Role.objects.filter(email__person=user.get_profile(), name="secr", group__acronym="secretariat"))
|
||||
|
||||
|
||||
def can_add_incoming_liaison(user):
|
||||
|
|
|
@ -33,7 +33,6 @@ class LiaisonDetailAdmin(admin.ModelAdmin):
|
|||
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
admin.site.register(LiaisonDetail, LiaisonDetailAdmin)
|
||||
|
||||
|
||||
class LiaisonPurposeAdmin(admin.ModelAdmin):
|
||||
ordering = ('purpose_text', )
|
||||
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
|
@ -138,3 +137,13 @@ class LegacyLiaisonUserAdmin(admin.ModelAdmin):
|
|||
list_display = ['pk', 'person_link', 'login_name', 'user_level', 'comment', ]
|
||||
raw_id_fields = [ 'person', ]
|
||||
admin.site.register(LegacyLiaisonUser, LegacyLiaisonUserAdmin)
|
||||
|
||||
class LiaisonStatementAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'title', 'from_name', 'to_name', 'submitted', 'purpose', 'related_to']
|
||||
list_display_links = ['id', 'title']
|
||||
ordering = ('title', )
|
||||
raw_id_fields = ('from_contact', 'related_to', 'from_group', 'to_group', 'attachments')
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.liaisons.models import LiaisonStatement
|
||||
admin.site.register(LiaisonStatement, LiaisonStatementAdmin)
|
||||
|
||||
|
|
|
@ -425,3 +425,6 @@ def liaison_form_factory(request, **kwargs):
|
|||
elif can_add_incoming_liaison(user):
|
||||
return IncomingLiaisonForm(user, **kwargs)
|
||||
return None
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.liaisons.formsREDESIGN import *
|
||||
|
|
455
ietf/liaisons/formsREDESIGN.py
Normal file
455
ietf/liaisons/formsREDESIGN.py
Normal file
|
@ -0,0 +1,455 @@
|
|||
import datetime
|
||||
from email.utils import parseaddr
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
from django.forms.util import ErrorList
|
||||
from django.forms.fields import email_re
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from ietf.liaisons.accounts import (can_add_outgoing_liaison, can_add_incoming_liaison,
|
||||
get_person_for_user, is_secretariat, is_sdo_liaison_manager)
|
||||
from ietf.liaisons.utils import IETFHM
|
||||
from ietf.liaisons.widgets import (FromWidget, ReadOnlyWidget, ButtonWidget,
|
||||
ShowAttachmentsWidget, RelatedLiaisonWidget)
|
||||
from ietf.liaisons.models import LiaisonStatement, LiaisonStatementPurposeName
|
||||
from redesign.group.models import Group
|
||||
from redesign.person.models import Person
|
||||
|
||||
|
||||
class LiaisonForm(forms.Form):
|
||||
from_field = forms.ChoiceField(widget=FromWidget, label=u'From')
|
||||
replyto = forms.CharField(label=u'Reply to')
|
||||
organization = forms.ChoiceField()
|
||||
to_poc = forms.CharField(widget=ReadOnlyWidget, label="POC", required=False)
|
||||
response_contact = forms.CharField(required=False, max_length=255)
|
||||
technical_contact = forms.CharField(required=False, max_length=255)
|
||||
cc1 = forms.CharField(widget=forms.Textarea, label="CC", required=False, help_text='Please insert one email address per line')
|
||||
purpose = forms.ChoiceField()
|
||||
purpose_text = forms.CharField(widget=forms.Textarea, label='Other purpose')
|
||||
deadline_date = forms.DateField(label='Deadline')
|
||||
submitted_date = forms.DateField(label='Submission date', initial=datetime.date.today())
|
||||
title = forms.CharField(label=u'Title')
|
||||
body = forms.CharField(widget=forms.Textarea, required=False)
|
||||
attachments = forms.CharField(label='Attachments', widget=ShowAttachmentsWidget, required=False)
|
||||
attach_title = forms.CharField(label='Title', required=False)
|
||||
attach_file = forms.FileField(label='File', required=False)
|
||||
attach_button = forms.CharField(label='',
|
||||
widget=ButtonWidget(label='Attach', show_on='id_attachments',
|
||||
require=['id_attach_title', 'id_attach_file'],
|
||||
required_label='title and file'),
|
||||
required=False)
|
||||
related_to = forms.ModelChoiceField(LiaisonStatement.objects.all(), label=u'Related Liaison', widget=RelatedLiaisonWidget, required=False)
|
||||
|
||||
fieldsets = [('From', ('from_field', 'replyto')),
|
||||
('To', ('organization', 'to_poc')),
|
||||
('Other email addresses', ('response_contact', 'technical_contact', 'cc1')),
|
||||
('Purpose', ('purpose', 'purpose_text', 'deadline_date')),
|
||||
('References', ('related_to', )),
|
||||
('Liaison Statement', ('title', 'submitted_date', 'body', 'attachments')),
|
||||
('Add attachment', ('attach_title', 'attach_file', 'attach_button')),
|
||||
]
|
||||
|
||||
class Media:
|
||||
js = ("/js/jquery-1.5.1.min.js",
|
||||
"/js/jquery-ui-1.8.11.custom.min.js",
|
||||
"/js/liaisons.js", )
|
||||
|
||||
css = {'all': ("/css/liaisons.css",
|
||||
"/css/jquery-ui-themes/jquery-ui-1.8.11.custom.css")}
|
||||
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
self.user = user
|
||||
self.fake_person = None
|
||||
self.person = get_person_for_user(user)
|
||||
if kwargs.get('data', None):
|
||||
kwargs['data'].update({'person': self.person.pk})
|
||||
if is_secretariat(self.user) and 'from_fake_user' in kwargs['data'].keys():
|
||||
self.fake_person = Person.objects.get(pk=kwargs['data']['from_fake_user'])
|
||||
kwargs['data'].update({'person': self.fake_person.pk})
|
||||
|
||||
self.instance = kwargs.pop("instance", None)
|
||||
|
||||
super(LiaisonForm, self).__init__(*args, **kwargs)
|
||||
|
||||
# now copy in values from instance, like a ModelForm
|
||||
if self.instance:
|
||||
for name, field in self.fields.iteritems():
|
||||
try:
|
||||
x = getattr(self.instance, name)
|
||||
if name == "purpose": # proxy has a name-clash on purpose so help it
|
||||
x = x.order
|
||||
self.initial[name] = x
|
||||
except AttributeError:
|
||||
# we have some fields on the form that aren't in the model
|
||||
pass
|
||||
self.fields["purpose"].choices = [("", "---------")] + [(str(l.order), l.name) for l in LiaisonStatementPurposeName.objects.all()]
|
||||
self.hm = IETFHM
|
||||
self.set_from_field()
|
||||
self.set_replyto_field()
|
||||
self.set_organization_field()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.as_div()
|
||||
|
||||
def get_post_only(self):
|
||||
return False
|
||||
|
||||
def set_required_fields(self):
|
||||
purpose = self.data.get('purpose', None)
|
||||
if purpose == '5':
|
||||
self.fields['purpose_text'].required=True
|
||||
else:
|
||||
self.fields['purpose_text'].required=False
|
||||
if purpose in ['1', '2']:
|
||||
self.fields['deadline_date'].required=True
|
||||
else:
|
||||
self.fields['deadline_date'].required=False
|
||||
|
||||
def reset_required_fields(self):
|
||||
self.fields['purpose_text'].required=True
|
||||
self.fields['deadline_date'].required=True
|
||||
|
||||
def set_from_field(self):
|
||||
assert NotImplemented
|
||||
|
||||
def set_replyto_field(self):
|
||||
email = self.person.email_address()
|
||||
self.fields['replyto'].initial = email
|
||||
|
||||
def set_organization_field(self):
|
||||
assert NotImplemented
|
||||
|
||||
def as_div(self):
|
||||
return render_to_string('liaisons/liaisonform.html', {'form': self})
|
||||
|
||||
def get_fieldsets(self):
|
||||
if not self.fieldsets:
|
||||
yield dict(name=None, fields=self)
|
||||
else:
|
||||
for fieldset, fields in self.fieldsets:
|
||||
fieldset_dict = dict(name=fieldset, fields=[])
|
||||
for field_name in fields:
|
||||
if field_name in self.fields.keyOrder:
|
||||
fieldset_dict['fields'].append(self[field_name])
|
||||
if not fieldset_dict['fields']:
|
||||
# if there is no fields in this fieldset, we continue to next fieldset
|
||||
continue
|
||||
yield fieldset_dict
|
||||
|
||||
def full_clean(self):
|
||||
self.set_required_fields()
|
||||
super(LiaisonForm, self).full_clean()
|
||||
self.reset_required_fields()
|
||||
|
||||
def has_attachments(self):
|
||||
for key in self.files.keys():
|
||||
if key.startswith('attach_file_') and key.replace('file', 'title') in self.data.keys():
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_email(self, value):
|
||||
if not value:
|
||||
return
|
||||
emails = value.split(',')
|
||||
for email in emails:
|
||||
name, addr = parseaddr(email)
|
||||
if not email_re.search(addr):
|
||||
raise forms.ValidationError('Invalid email address: %s' % addr)
|
||||
|
||||
def clean_response_contact(self):
|
||||
value = self.cleaned_data.get('response_contact', None)
|
||||
self.check_email(value)
|
||||
return value
|
||||
|
||||
def clean_technical_contact(self):
|
||||
value = self.cleaned_data.get('technical_contact', None)
|
||||
self.check_email(value)
|
||||
return value
|
||||
|
||||
def clean_reply_to(self):
|
||||
value = self.cleaned_data.get('reply_to', None)
|
||||
self.check_email(value)
|
||||
return value
|
||||
|
||||
def clean(self):
|
||||
if not self.cleaned_data.get('body', None) and not self.has_attachments():
|
||||
self._errors['body'] = ErrorList([u'You must provide a body or attachment files'])
|
||||
self._errors['attachments'] = ErrorList([u'You must provide a body or attachment files'])
|
||||
return self.cleaned_data
|
||||
|
||||
def get_from_entity(self):
|
||||
organization_key = self.cleaned_data.get('from_field')
|
||||
return self.hm.get_entity_by_key(organization_key)
|
||||
|
||||
def get_to_entity(self):
|
||||
organization_key = self.cleaned_data.get('organization')
|
||||
return self.hm.get_entity_by_key(organization_key)
|
||||
|
||||
def get_poc(self, organization):
|
||||
return ', '.join([i.email_address() for i in organization.get_poc()])
|
||||
|
||||
def clean_cc1(self):
|
||||
value = self.cleaned_data.get('cc1', '')
|
||||
result = []
|
||||
errors = []
|
||||
for address in value.split('\n'):
|
||||
address = address.strip();
|
||||
if not address:
|
||||
continue
|
||||
try:
|
||||
self.check_email(address)
|
||||
except forms.ValidationError:
|
||||
errors.append(address)
|
||||
result.append(address)
|
||||
if errors:
|
||||
raise forms.ValidationError('Invalid email addresses: %s' % ', '.join(errors))
|
||||
return ','.join(result)
|
||||
|
||||
def get_cc(self, from_entity, to_entity):
|
||||
#Old automatic Cc code, now we retrive it from cleaned_data
|
||||
#persons = to_entity.get_cc(self.person)
|
||||
#persons += from_entity.get_from_cc(self.person)
|
||||
#return ', '.join(['%s <%s>' % i.email() for i in persons])
|
||||
cc = self.cleaned_data.get('cc1', '')
|
||||
return cc
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
l = self.instance
|
||||
if not l:
|
||||
l = LiaisonStatement()
|
||||
|
||||
l.title = self.cleaned_data["title"]
|
||||
l.purpose = LiaisonStatementPurposeName.objects.get(order=self.cleaned_data["purpose"])
|
||||
l.body = self.cleaned_data["body"].strip()
|
||||
l.deadline = self.cleaned_data["deadline_date"]
|
||||
l.related_to = self.cleaned_data["related_to"]
|
||||
l.reply_to = self.cleaned_data["replyto"]
|
||||
l.response_contact = self.cleaned_data["response_contact"]
|
||||
l.technical_contact = self.cleaned_data["technical_contact"]
|
||||
|
||||
now = datetime.datetime.now()
|
||||
|
||||
l.modified = now
|
||||
l.submitted = datetime.datetime.combine(self.cleaned_data["submitted_date"], now.time())
|
||||
if self.cleaned_data.get("approval"): # FIXME
|
||||
if not l.approved:
|
||||
l.approved = now
|
||||
|
||||
self.save_extra_fields(l)
|
||||
l.save() # we have to save here to make sure we get an id for the attachments
|
||||
self.save_attachments(l)
|
||||
|
||||
return l
|
||||
|
||||
def save_extra_fields(self, liaison):
|
||||
from_entity = self.get_from_entity()
|
||||
print from_entity, type(from_entity)
|
||||
print self.cleaned_data.get("from_field")
|
||||
liason.from_name = from_entity.name
|
||||
print from_entity.obj # FIXME? c.get("from_field")
|
||||
liason.from_group = from_entity.obj
|
||||
liason.from_contact = self.person # FIXME?
|
||||
|
||||
organization = self.get_to_entity()
|
||||
liason.to_name = organization.name
|
||||
print organization.obj # FIXME? self.cleaned_data.get('organization')
|
||||
liason.to_group = organization.obj
|
||||
liason.to_contact = self.get_poc(organization)
|
||||
|
||||
liaison.cc = self.get_cc(from_entity, organization)
|
||||
|
||||
def save_attachments(self, instance):
|
||||
return # FIXME
|
||||
for key in self.files.keys():
|
||||
title_key = key.replace('file', 'title')
|
||||
if not key.startswith('attach_file_') or not title_key in self.data.keys():
|
||||
continue
|
||||
attached_file = self.files.get(key)
|
||||
extension=attached_file.name.rsplit('.', 1)
|
||||
if len(extension) > 1:
|
||||
extension = '.' + extension[1]
|
||||
else:
|
||||
extension = ''
|
||||
attach = Uploads.objects.create(
|
||||
file_title = self.data.get(title_key),
|
||||
person = self.person,
|
||||
detail = instance,
|
||||
file_extension = extension,
|
||||
)
|
||||
attach_file = open('%sfile%s%s' % (settings.LIAISON_ATTACH_PATH, attach.pk, attach.file_extension), 'w')
|
||||
attach_file.write(attached_file.read())
|
||||
attach_file.close()
|
||||
|
||||
def clean_title(self):
|
||||
title = self.cleaned_data.get('title', None)
|
||||
if self.instance and self.instance.pk:
|
||||
exclude_filter = {'pk': self.instance.pk}
|
||||
else:
|
||||
exclude_filter = {}
|
||||
exists = bool(LiaisonStatement.objects.exclude(**exclude_filter).filter(title__iexact=title).count())
|
||||
if exists:
|
||||
raise forms.ValidationError('A liaison statement with the same title has previously been submitted.')
|
||||
return title
|
||||
|
||||
|
||||
class IncomingLiaisonForm(LiaisonForm):
|
||||
|
||||
def set_from_field(self):
|
||||
if is_secretariat(self.user):
|
||||
sdos = Group.objects.filter(type="sdo", state="active")
|
||||
else:
|
||||
sdos = Group.objects.filter(type="sdo", state="active", role__email__person=self.person, role__name__in=("liaiman", "auth")).distinct()
|
||||
self.fields['from_field'].choices = [('sdo_%s' % i.pk, i.name) for i in sdos.order_by("name")]
|
||||
self.fields['from_field'].widget.submitter = unicode(self.person)
|
||||
|
||||
def set_organization_field(self):
|
||||
self.fields['organization'].choices = self.hm.get_all_incoming_entities()
|
||||
|
||||
def get_post_only(self):
|
||||
from_entity = self.get_from_entity()
|
||||
if is_secretariat(self.user) or Role.objects.filter(email__person=self.person, group=from_entity.obj, name="auth"):
|
||||
return False
|
||||
return True
|
||||
|
||||
def clean(self):
|
||||
if 'send' in self.data.keys() and self.get_post_only():
|
||||
self._errors['from_field'] = ErrorList([u'As an IETF Liaison Manager you can not send an incoming liaison statements, you only can post them'])
|
||||
return super(IncomingLiaisonForm, self).clean()
|
||||
|
||||
|
||||
def liaison_manager_sdos(person):
|
||||
return Group.objects.filter(type="sdo", state="active", role__email__person=person, role__name="liaiman").distinct()
|
||||
|
||||
class OutgoingLiaisonForm(LiaisonForm):
|
||||
|
||||
to_poc = forms.CharField(label="POC", required=True)
|
||||
approved = forms.BooleanField(label="Obtained prior approval", required=False)
|
||||
other_organization = forms.CharField(label="Other SDO", required=True)
|
||||
|
||||
def get_to_entity(self):
|
||||
organization_key = self.cleaned_data.get('organization')
|
||||
organization = self.hm.get_entity_by_key(organization_key)
|
||||
if organization_key == 'othersdo' and self.cleaned_data.get('other_organization', None):
|
||||
organization.name=self.cleaned_data['other_organization']
|
||||
return organization
|
||||
|
||||
def set_from_field(self):
|
||||
if is_secretariat(self.user):
|
||||
self.fields['from_field'].choices = self.hm.get_all_incoming_entities()
|
||||
elif is_sdo_liaison_manager(self.person):
|
||||
self.fields['from_field'].choices = self.hm.get_all_incoming_entities()
|
||||
all_entities = []
|
||||
for i in self.hm.get_entities_for_person(self.person):
|
||||
all_entities += i[1]
|
||||
if all_entities:
|
||||
self.fields['from_field'].widget.full_power_on = [i[0] for i in all_entities]
|
||||
self.fields['from_field'].widget.reduced_to_set = ['sdo_%s' % i.pk for i in liaison_manager_sdos(self.person)]
|
||||
else:
|
||||
self.fields['from_field'].choices = self.hm.get_entities_for_person(self.person)
|
||||
self.fields['from_field'].widget.submitter = unicode(self.person)
|
||||
self.fieldsets[0] = ('From', ('from_field', 'replyto', 'approved'))
|
||||
|
||||
def set_organization_field(self):
|
||||
# If the user is a liaison manager and is nothing more, reduce the To field to his SDOs
|
||||
if not self.hm.get_entities_for_person(self.person) and is_sdo_liaison_manager(self.person):
|
||||
self.fields['organization'].choices = [('sdo_%s' % i.pk, i.name) for i in liaison_manager_sdos()]
|
||||
else:
|
||||
self.fields['organization'].choices = self.hm.get_all_outgoing_entities()
|
||||
self.fieldsets[1] = ('To', ('organization', 'other_organization', 'to_poc'))
|
||||
|
||||
def set_required_fields(self):
|
||||
super(OutgoingLiaisonForm, self).set_required_fields()
|
||||
organization = self.data.get('organization', None)
|
||||
if organization == 'othersdo':
|
||||
self.fields['other_organization'].required=True
|
||||
else:
|
||||
self.fields['other_organization'].required=False
|
||||
|
||||
def reset_required_fields(self):
|
||||
super(OutgoingLiaisonForm, self).reset_required_fields()
|
||||
self.fields['other_organization'].required=True
|
||||
|
||||
def get_poc(self, organization):
|
||||
return self.cleaned_data['to_poc']
|
||||
|
||||
def save_extra_fields(self, liaison):
|
||||
raise NotImplemented
|
||||
super(OutgoingLiaisonForm, self).save_extra_fields(liaison)
|
||||
from_entity = self.get_from_entity()
|
||||
needs_approval = from_entity.needs_approval(self.person)
|
||||
if not needs_approval or self.cleaned_data.get('approved', False):
|
||||
approved = True
|
||||
approval_date = datetime.datetime.now()
|
||||
else:
|
||||
approved = False
|
||||
approval_date = None
|
||||
approval = OutgoingLiaisonApproval.objects.create(
|
||||
approved = approved,
|
||||
approval_date = approval_date)
|
||||
liaison.approval = approval
|
||||
liaison.save()
|
||||
|
||||
def clean_to_poc(self):
|
||||
value = self.cleaned_data.get('to_poc', None)
|
||||
self.check_email(value)
|
||||
return value
|
||||
|
||||
def clean_organization(self):
|
||||
to_code = self.cleaned_data.get('organization', None)
|
||||
from_code = self.cleaned_data.get('from_field', None)
|
||||
if not to_code or not from_code:
|
||||
return to_code
|
||||
all_entities = []
|
||||
person = self.fake_person or self.person
|
||||
for i in self.hm.get_entities_for_person(person):
|
||||
all_entities += i[1]
|
||||
# If the from entity is one in wich the user has full privileges the to entity could be anyone
|
||||
if from_code in [i[0] for i in all_entities]:
|
||||
return to_code
|
||||
sdo_codes = ['sdo_%s' % i.pk for i in liaison_manager_sdos(self.person)]
|
||||
if to_code in sdo_codes:
|
||||
return to_code
|
||||
entity = self.get_to_entity()
|
||||
entity_name = entity and entity.name or to_code
|
||||
if self.fake_person:
|
||||
raise forms.ValidationError('%s is not allowed to send a liaison to: %s' % (self.fake_person, entity_name))
|
||||
else:
|
||||
raise forms.ValidationError('You are not allowed to send a liaison to: %s' % entity_name)
|
||||
|
||||
|
||||
class EditLiaisonForm(LiaisonForm):
|
||||
|
||||
from_field = forms.CharField(widget=forms.TextInput, label=u'From')
|
||||
replyto = forms.CharField(label=u'Reply to', widget=forms.TextInput)
|
||||
organization = forms.CharField(widget=forms.TextInput)
|
||||
to_poc = forms.CharField(widget=forms.TextInput, label="POC", required=False)
|
||||
cc1 = forms.CharField(widget=forms.TextInput, label="CC", required=False)
|
||||
|
||||
class Meta:
|
||||
fields = ('from_raw_body', 'to_body', 'to_poc', 'cc1', 'last_modified_date', 'title',
|
||||
'response_contact', 'technical_contact', 'purpose_text', 'body',
|
||||
'deadline_date', 'purpose', 'replyto', 'related_to')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EditLiaisonForm, self).__init__(*args, **kwargs)
|
||||
self.edit = True
|
||||
self.initial.update({'attachments': self.instance.uploads_set.all()})
|
||||
self.fields['submitted_date'].initial = self.instance.submitted_date
|
||||
|
||||
def set_from_field(self):
|
||||
self.fields['from_field'].initial = self.instance.from_body
|
||||
|
||||
def set_replyto_field(self):
|
||||
self.fields['replyto'].initial = self.instance.replyto
|
||||
|
||||
def set_organization_field(self):
|
||||
self.fields['organization'].initial = self.instance.to_body
|
||||
|
||||
def save_extra_fields(self, liaison):
|
||||
liaison.from_name = self.cleaned_data.get('from_field')
|
||||
liaison.to_name = self.cleaned_data.get('organization')
|
||||
liaison.to_contact = self.cleaned_data['to_poc']
|
||||
liaison.cc = self.cleaned_data['cc1']
|
||||
|
|
@ -322,7 +322,7 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES or hasattr(settings, "IMPORTING_FROM_O
|
|||
|
||||
from_group = models.ForeignKey(Group, related_name="liaisonstatement_from_set", null=True, blank=True, help_text="From body, if it exists")
|
||||
from_name = models.CharField(max_length=255, help_text="Name of the sender body")
|
||||
from_contact = models.ForeignKey(Email)
|
||||
from_contact = models.ForeignKey(Email, blank=True, null=True)
|
||||
to_group = models.ForeignKey(Group, related_name="liaisonstatement_to_set", null=True, blank=True, help_text="To body, if it exists")
|
||||
to_name = models.CharField(max_length=255, help_text="Name of the recipient body")
|
||||
to_contact = models.CharField(blank=True, max_length=255, help_text="Contacts at to body")
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
from redesign.proxy_utils import TranslatingManager
|
||||
from ietf.liaisons.models import LiaisonStatement
|
||||
from redesign.doc.models import Document
|
||||
|
||||
class LiaisonDetailProxy(LiaisonStatement):
|
||||
objects = TranslatingManager(dict(meeting_num="number"))
|
||||
objects = TranslatingManager(dict(submitted_date="submitted",
|
||||
deadline_date="deadline",
|
||||
to_body="to_name",
|
||||
from_raw_body="from_name"))
|
||||
|
||||
def from_object(self, base):
|
||||
for f in base._meta.fields:
|
||||
|
@ -16,7 +20,7 @@ class LiaisonDetailProxy(LiaisonStatement):
|
|||
#person = models.ForeignKey(PersonOrOrgInfo, null=True, db_column='person_or_org_tag')
|
||||
@property
|
||||
def person(self):
|
||||
return self.submitted_by
|
||||
return self.from_contact.person if self.from_contact else ""
|
||||
#submitted_date = models.DateField(null=True, blank=True)
|
||||
@property
|
||||
def submitted_date(self):
|
||||
|
@ -44,23 +48,45 @@ class LiaisonDetailProxy(LiaisonStatement):
|
|||
#deadline_date = models.DateField(null=True, blank=True)
|
||||
@property
|
||||
def deadline_date(self):
|
||||
return self.deadline.date()
|
||||
return self.deadline
|
||||
#cc1 = models.TextField(blank=True, null=True)
|
||||
@property
|
||||
def cc1(self):
|
||||
return self.cc
|
||||
#cc2 = models.CharField(blank=True, null=True, max_length=50) # unused
|
||||
@property
|
||||
def cc2(self):
|
||||
return ""
|
||||
#submitter_name = models.CharField(blank=True, null=True, max_length=255)
|
||||
@property
|
||||
def submitter_name(self):
|
||||
i = self.to_name.find('<')
|
||||
if i > 0:
|
||||
return self.to_name[:i - 1]
|
||||
else:
|
||||
return self.to_name
|
||||
#submitter_email = models.CharField(blank=True, null=True, max_length=255)
|
||||
@property
|
||||
def submitter_email(self):
|
||||
import re
|
||||
re_email = re.compile("<(.*)>")
|
||||
match = re_email.search(self.to_name)
|
||||
if match:
|
||||
return match.group(1)
|
||||
else:
|
||||
return ""
|
||||
#by_secretariat = models.IntegerField(null=True, blank=True)
|
||||
@property
|
||||
def by_secretariat(self):
|
||||
return False
|
||||
return not self.from_contact
|
||||
#to_poc = models.CharField(blank=True, null=True, max_length=255)
|
||||
@property
|
||||
def to_poc(self):
|
||||
return self.to_contact
|
||||
#to_email = models.CharField(blank=True, null=True, max_length=255) # unused
|
||||
#to_email = models.CharField(blank=True, null=True, max_length=255)
|
||||
@property
|
||||
def to_email(self):
|
||||
return ""
|
||||
#purpose = models.ForeignKey(LiaisonPurpose,null=True)
|
||||
#replyto = models.CharField(blank=True, null=True, max_length=255)
|
||||
@property
|
||||
|
@ -84,6 +110,15 @@ class LiaisonDetailProxy(LiaisonStatement):
|
|||
return bool(self.approved)
|
||||
#action_taken = models.BooleanField(default=False, db_column='taken_care') # same name
|
||||
#related_to = models.ForeignKey('LiaisonDetail', blank=True, null=True) # same name
|
||||
|
||||
@property
|
||||
def uploads_set(self):
|
||||
return UploadsProxy.objects.filter(liaisonstatement=self).order_by('name')
|
||||
|
||||
@property
|
||||
def liaisondetail_set(self):
|
||||
return self.liaisonstatement_set
|
||||
|
||||
def __str__(self):
|
||||
return unicode(self)
|
||||
def __unicode__(self):
|
||||
|
@ -93,7 +128,7 @@ class LiaisonDetailProxy(LiaisonStatement):
|
|||
def from_sdo(self):
|
||||
return self.from_group if self.from_group and self.from_group.type_id == "sdo" else None
|
||||
def from_email(self):
|
||||
self.from_contact
|
||||
self.from_contact.address
|
||||
def get_absolute_url(self):
|
||||
return '/liaison/%d/' % self.detail_id
|
||||
class Meta:
|
||||
|
@ -150,3 +185,29 @@ class LiaisonDetailProxy(LiaisonStatement):
|
|||
|
||||
def is_pending(self):
|
||||
return not self.approved
|
||||
|
||||
class UploadsProxy(Document):
|
||||
#file_id = models.AutoField(primary_key=True)
|
||||
@property
|
||||
def file_id(self):
|
||||
return int(self.external_url.split(".")[0])
|
||||
#file_title = models.CharField(blank=True, max_length=255)
|
||||
@property
|
||||
def file_title(self):
|
||||
return self.title
|
||||
#person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag')
|
||||
#file_extension = models.CharField(blank=True, max_length=10)
|
||||
@property
|
||||
def file_extension(self):
|
||||
t = self.external_url.split(".")
|
||||
if len(t) > 1:
|
||||
return "." + t[1]
|
||||
else:
|
||||
return ""
|
||||
#detail = models.ForeignKey(LiaisonDetail)
|
||||
@property
|
||||
def detail(self):
|
||||
return self.liaisonstatement_set.all()[0]
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
import datetime
|
||||
|
||||
from ietf.utils.test_utils import SimpleUrlTestCase, canonicalize_feed, canonicalize_sitemap
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
import django.test
|
||||
from pyquery import PyQuery
|
||||
|
||||
from ietf.utils.test_utils import SimpleUrlTestCase, canonicalize_feed, canonicalize_sitemap, login_testing_unauthorized
|
||||
from ietf.utils.test_runner import mail_outbox
|
||||
from ietf.utils.test_data import make_test_data
|
||||
|
||||
class LiaisonsUrlTestCase(SimpleUrlTestCase):
|
||||
def testUrls(self):
|
||||
|
@ -11,3 +20,91 @@ class LiaisonsUrlTestCase(SimpleUrlTestCase):
|
|||
return canonicalize_sitemap(content)
|
||||
else:
|
||||
return content
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.liaisons.models import LiaisonStatement
|
||||
from redesign.person.models import Person, Email
|
||||
from redesign.group.models import Group, Role
|
||||
|
||||
def make_liaison_models():
|
||||
sdo = Group.objects.create(
|
||||
name="United League of Marsmen",
|
||||
acronym="",
|
||||
state_id="active",
|
||||
type_id="sdo",
|
||||
)
|
||||
|
||||
u = User.objects.create(username="zrk")
|
||||
p = Person.objects.create(
|
||||
name="Zrk Brekkk",
|
||||
ascii="Zrk Brekkk",
|
||||
user=u)
|
||||
email = Email.objects.create(
|
||||
address="zrk@ulm.mars",
|
||||
person=p)
|
||||
Role.objects.create(
|
||||
name_id="liaiman",
|
||||
group=sdo,
|
||||
email=email)
|
||||
|
||||
mars_group = Group.objects.get(acronym="mars")
|
||||
|
||||
l = LiaisonStatement.objects.create(
|
||||
title="Comment from United League of Marsmen",
|
||||
purpose_id="comment",
|
||||
body="The recently proposed Martian Standard for Communication Links neglects the special ferro-magnetic conditions of the Martian soil.",
|
||||
deadline=datetime.date.today() + datetime.timedelta(days=7),
|
||||
related_to=None,
|
||||
from_group=sdo,
|
||||
from_name=sdo.name,
|
||||
from_contact=email,
|
||||
to_group=mars_group,
|
||||
to_name=mars_group.name,
|
||||
to_contact="%s@ietf.org" % mars_group.acronym,
|
||||
reply_to=email.address,
|
||||
response_contact="",
|
||||
technical_contact="",
|
||||
cc="",
|
||||
submitted=datetime.datetime.now(),
|
||||
modified=datetime.datetime.now(),
|
||||
approved=datetime.datetime.now(),
|
||||
action_taken=False,
|
||||
)
|
||||
return l
|
||||
|
||||
|
||||
class LiaisonManagementTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
def test_taken_care_of(self):
|
||||
make_test_data()
|
||||
liaison = make_liaison_models()
|
||||
|
||||
url = urlreverse('liaison_detail', kwargs=dict(object_id=liaison.pk))
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[name=do_action_taken]')), 0)
|
||||
|
||||
# logged in and get
|
||||
self.client.login(remote_user="secretary")
|
||||
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[name=do_action_taken]')), 1)
|
||||
|
||||
# mark action taken
|
||||
r = self.client.post(url, dict(do_action_taken=1))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form input[name=do_action_taken]')), 0)
|
||||
liaison = LiaisonStatement.objects.get(id=liaison.id)
|
||||
self.assertTrue(liaison.action_taken)
|
||||
|
||||
|
||||
|
||||
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
# the above tests only work with the new schema
|
||||
del LiaisonManagementTestCase
|
||||
|
|
|
@ -22,16 +22,19 @@ class FakePerson(object):
|
|||
def email(self):
|
||||
return (self.name, self.address)
|
||||
|
||||
# the following is a biggish object hierarchy modeling the entity
|
||||
# the following is a biggish object hierarchy abstracting the entity
|
||||
# names and auth rules for posting liaison statements in a sort of
|
||||
# semi-declarational way
|
||||
# semi-declarational (and perhaps overengineered given the revamped
|
||||
# schema) way - unfortunately, it's never been strong enough to do so
|
||||
# fine-grained enough so the form code also has some rules
|
||||
|
||||
def role_persons_with_fixed_email(group, role_name):
|
||||
from redesign.group.models import Role
|
||||
res = []
|
||||
for r in Role.objects.filter(group=group, name=role_name).select_related("email"):
|
||||
p = r.email.person
|
||||
# evil hack to make email() return the right address
|
||||
p.email = (lambda email: (lambda x: (x.name, email.address)))(r.email)
|
||||
# proxy hack to make email() return the right address
|
||||
p.email = (lambda name, address: (lambda: (name, address)))(p.name, r.email.address)
|
||||
res.append(p)
|
||||
return res
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ from ietf.liaisons.forms import liaison_form_factory
|
|||
from ietf.liaisons.models import LiaisonDetail, OutgoingLiaisonApproval
|
||||
from ietf.liaisons.utils import IETFHM
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.liaisons.proxy import LiaisonDetailProxy as LiaisonDetail
|
||||
|
||||
|
||||
@can_submit_liaison
|
||||
def add_liaison(request, liaison=None):
|
||||
|
@ -81,6 +84,7 @@ def get_info(request):
|
|||
full_list.sort(lambda x,y: cmp(x[1], y[1]))
|
||||
full_list = [(person.pk, person.email())] + full_list
|
||||
result.update({'full_list': full_list})
|
||||
|
||||
json_result = simplejson.dumps(result)
|
||||
return HttpResponse(json_result, mimetype='text/javascript')
|
||||
|
||||
|
@ -93,6 +97,19 @@ def _fake_email_view(request, liaison):
|
|||
'liaison': liaison},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
def approvable_liaison_statements(group_codes):
|
||||
# this is a bit complicated because IETFHM encodes the
|
||||
# groups, it should just give us a list of ids or acronyms
|
||||
group_acronyms = []
|
||||
group_ids = []
|
||||
for x in group_codes:
|
||||
if "_" in x:
|
||||
group_ids.append(x.split("_")[1])
|
||||
else:
|
||||
group_acronyms.append(x)
|
||||
|
||||
return LiaisonDetail.objects.filter(approved=None).filter(Q(from_group__acronym__in=group_acronyms) | Q (from_group__pk__in=group_ids))
|
||||
|
||||
def liaison_list(request):
|
||||
user = request.user
|
||||
|
@ -104,7 +121,10 @@ def liaison_list(request):
|
|||
person = get_person_for_user(request.user)
|
||||
if person:
|
||||
approval_codes = IETFHM.get_all_can_approve_codes(person)
|
||||
can_approve = LiaisonDetail.objects.filter(approval__isnull=False, approval__approved=False, from_raw_code__in=approval_codes).count()
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
can_approve = approvable_liaison_statements(approval_codes).count()
|
||||
else:
|
||||
can_approve = LiaisonDetail.objects.filter(approval__isnull=False, approval__approved=False, from_raw_code__in=approval_codes).count()
|
||||
|
||||
order = request.GET.get('order_by', 'submitted_date')
|
||||
plain_order = order
|
||||
|
@ -121,7 +141,10 @@ def liaison_list(request):
|
|||
order = plain_order
|
||||
else:
|
||||
order = '-%s' % plain_order
|
||||
public_liaisons = LiaisonDetail.objects.filter(Q(approval__isnull=True)|Q(approval__approved=True)).order_by(order)
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
public_liaisons = LiaisonDetail.objects.exclude(approved=None).order_by(order)
|
||||
else:
|
||||
public_liaisons = LiaisonDetail.objects.filter(Q(approval__isnull=True)|Q(approval__approved=True)).order_by(order)
|
||||
|
||||
return object_list(request, public_liaisons,
|
||||
allow_empty=True,
|
||||
|
@ -139,7 +162,10 @@ def liaison_list(request):
|
|||
def liaison_approval_list(request):
|
||||
person = get_person_for_user(request.user)
|
||||
approval_codes = IETFHM.get_all_can_approve_codes(person)
|
||||
to_approve = LiaisonDetail.objects.filter(approval__isnull=False, approval__approved=False, from_raw_code__in=approval_codes).order_by("-submitted_date")
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
to_approve = approvable_liaison_statements(approval_codes).order_by("-submitted")
|
||||
else:
|
||||
to_approve = LiaisonDetail.objects.filter(approval__isnull=False, approval__approved=False, from_raw_code__in=approval_codes).order_by("-submitted_date")
|
||||
|
||||
return object_list(request, to_approve,
|
||||
allow_empty=True,
|
||||
|
@ -183,7 +209,7 @@ def _can_take_care(liaison, user):
|
|||
return False
|
||||
|
||||
if user.is_authenticated():
|
||||
if user.groups.filter(name__in=LIAISON_EDIT_GROUPS):
|
||||
if is_secretariat(user):
|
||||
return True
|
||||
else:
|
||||
return _find_person_in_emails(liaison, get_person_for_user(user))
|
||||
|
@ -199,6 +225,8 @@ def _find_person_in_emails(liaison, person):
|
|||
liaison.technical_contact] if e ])
|
||||
for email in emails.split(','):
|
||||
name, addr = parseaddr(email)
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
person.emailaddress_set = person.email_set
|
||||
if email_re.search(addr) and person.emailaddress_set.filter(address=addr):
|
||||
return True
|
||||
elif addr in ('chair@ietf.org', 'iesg@ietf.org') and is_ietfchair(person):
|
||||
|
@ -211,8 +239,12 @@ def _find_person_in_emails(liaison, person):
|
|||
|
||||
|
||||
def liaison_detail(request, object_id):
|
||||
qfilter = Q(approval__isnull=True)|Q(approval__approved=True)
|
||||
public_liaisons = LiaisonDetail.objects.filter(qfilter).order_by("-submitted_date")
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
qfilter = Q()
|
||||
public_liaisons = LiaisonDetail.objects.exclude(approved=None).order_by("-submitted_date")
|
||||
else:
|
||||
qfilter = Q(approval__isnull=True)|Q(approval__approved=True)
|
||||
public_liaisons = LiaisonDetail.objects.filter(qfilter).order_by("-submitted_date")
|
||||
liaison = get_object_or_404(public_liaisons, pk=object_id)
|
||||
can_edit = False
|
||||
user = request.user
|
||||
|
@ -226,6 +258,7 @@ def liaison_detail(request, object_id):
|
|||
relations = liaison.liaisondetail_set.filter(qfilter)
|
||||
return object_detail(request,
|
||||
public_liaisons,
|
||||
template_name="liaisons/liaisondetail_detail.html",
|
||||
object_id=object_id,
|
||||
extra_context = {'can_edit': can_edit,
|
||||
'relations': relations,
|
||||
|
@ -255,7 +288,11 @@ def ajax_liaison_list(request):
|
|||
order = plain_order
|
||||
else:
|
||||
order = '-%s' % plain_order
|
||||
public_liaisons = LiaisonDetail.objects.filter(Q(approval__isnull=True)|Q(approval__approved=True)).order_by(order)
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
public_liaisons = LiaisonDetail.objects.exclude(approved=None).order_by(order)
|
||||
else:
|
||||
public_liaisons = LiaisonDetail.objects.filter(Q(approval__isnull=True)|Q(approval__approved=True)).order_by(order)
|
||||
|
||||
return object_list(request, public_liaisons,
|
||||
allow_empty=True,
|
||||
|
|
|
@ -89,6 +89,8 @@ class RelatedLiaisonWidget(TextInput):
|
|||
deselect = 'none'
|
||||
else:
|
||||
from ietf.liaisons.models import LiaisonDetail
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.liaisons.proxy import LiaisonDetail
|
||||
liaison = LiaisonDetail.objects.get(pk=value)
|
||||
title = liaison.title
|
||||
if not title:
|
||||
|
|
|
@ -139,7 +139,13 @@ for o in SDOs.objects.all().order_by("pk"):
|
|||
# of the rest of the role/person models for authentication and
|
||||
# authorization
|
||||
print "importing SDOs", o.pk, o.sdo_name
|
||||
Group.objects.get_or_create(name=o.sdo_name, type=type_names["sdo"])
|
||||
try:
|
||||
group = Group.objects.get(name=o.sdo_name, type=type_names["sdo"])
|
||||
except Group.DoesNotExist:
|
||||
group = Group(name=o.sdo_name, type=type_names["sdo"])
|
||||
|
||||
group.state_id = "active"
|
||||
group.save()
|
||||
|
||||
# Area
|
||||
for o in Area.objects.all():
|
||||
|
|
|
@ -32,16 +32,17 @@ from redesign.name.utils import name
|
|||
# - groups have been imported
|
||||
|
||||
purpose_mapping = {
|
||||
1: name(LiaisonStatementPurposeName, "action", "For action"),
|
||||
2: name(LiaisonStatementPurposeName, "comment", "For comment"),
|
||||
3: name(LiaisonStatementPurposeName, "info", "For information"),
|
||||
4: name(LiaisonStatementPurposeName, "response", "In response"),
|
||||
5: name(LiaisonStatementPurposeName, "other", "Other"),
|
||||
1: name(LiaisonStatementPurposeName, "action", "For action", order=1),
|
||||
2: name(LiaisonStatementPurposeName, "comment", "For comment", order=2),
|
||||
3: name(LiaisonStatementPurposeName, "info", "For information", order=3),
|
||||
4: name(LiaisonStatementPurposeName, "response", "In response", order=4),
|
||||
# we drop the "other" category here, it was virtuall unused in the old schema
|
||||
}
|
||||
|
||||
liaison_attachment_doctype = name(DocTypeName, "liai-att", "Liaison Attachment")
|
||||
|
||||
purpose_mapping[None] = purpose_mapping[3] # map unknown to "For information"
|
||||
purpose_mapping[5] = purpose_mapping[3] # "Other" is mapped to "For information" as default
|
||||
|
||||
system_email = Email.objects.get(person__name="(System)")
|
||||
obviously_bogus_date = datetime.date(1970, 1, 1)
|
||||
|
@ -145,7 +146,7 @@ for o in LiaisonDetail.objects.all().order_by("pk"):
|
|||
l.from_name = o.from_body().strip()
|
||||
l.from_group = get_body(l.from_name, o.from_raw_code) # try to establish link
|
||||
if not o.person:
|
||||
l.from_contact = system_email
|
||||
l.from_contact = None
|
||||
else:
|
||||
try:
|
||||
l.from_contact = Email.objects.get(address__iexact=o.from_email().address)
|
||||
|
@ -155,7 +156,7 @@ for o in LiaisonDetail.objects.all().order_by("pk"):
|
|||
if o.by_secretariat:
|
||||
l.to_name = o.submitter_name
|
||||
if o.submitter_email:
|
||||
l.to_name += " " + o.submitter_email
|
||||
l.to_name += " <%s>" % o.submitter_email
|
||||
else:
|
||||
l.to_name = o.to_body
|
||||
l.to_name = l.to_name.strip()
|
||||
|
@ -170,7 +171,12 @@ for o in LiaisonDetail.objects.all().order_by("pk"):
|
|||
|
||||
l.submitted = o.submitted_date
|
||||
l.modified = o.last_modified_date
|
||||
l.approved = o.approval.approval_date or l.modified or datetime.datetime.now() if o.approval and o.approval.approved else None
|
||||
if not o.approval:
|
||||
# no approval object means it's approved alright - weird, we
|
||||
# have to fake the approved date then
|
||||
l.approved = l.modified or l.submitted or datetime.datetime.now()
|
||||
else:
|
||||
l.approved = o.approval.approval_date if o.approval.approved else None
|
||||
|
||||
l.action_taken = o.action_taken
|
||||
|
||||
|
@ -184,7 +190,7 @@ for o in LiaisonDetail.objects.all().order_by("pk"):
|
|||
attachment.name = l.name() + ("-attachment-%s" % (i + 1))
|
||||
attachment.time = l.submitted
|
||||
# we should fixup the filenames, but meanwhile, store it here
|
||||
attachment.external_url = "%s.%s" % (u.file_id, u.file_extension)
|
||||
attachment.external_url = "%s%s" % (u.file_id, u.file_extension)
|
||||
attachment.save()
|
||||
|
||||
DocAlias.objects.get_or_create(document=attachment, name=attachment.name)
|
||||
|
|
Loading…
Reference in a new issue