import datetime from django import forms from django.forms.util import ErrorList 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_ietf_liaison_manager) from ietf.liaisons.models import LiaisonDetail, Uploads, OutgoingLiaisonApproval, SDOs from ietf.liaisons.utils import IETFHM from ietf.liaisons.widgets import (FromWidget, ReadOnlyWidget, ButtonWidget, ShowAttachmentsWidget) class LiaisonForm(forms.ModelForm): 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) cc1 = forms.CharField(widget=ReadOnlyWidget, label="CC", required=False) purpose_text = forms.CharField(widget=forms.Textarea, label='Other purpose') deadline_date = forms.DateField(label='Deadline') title = forms.CharField(label=u'Title') 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) fieldsets = [('From', ('from_field', 'replyto')), ('To', ('organization', 'to_poc')), ('Other email addresses', ('response_contact', 'technical_contact', 'cc1')), ('Purpose', ('purpose', 'purpose_text', 'deadline_date')), ('Liaison Statement', ('title', 'body', 'attachments')), ('Add attachment', ('attach_title', 'attach_file', 'attach_button')), ] class Meta: model = LiaisonDetail class Media: js = ("/js/jquery-1.4.2.min.js", "/js/jquery-ui-1.8.2.custom.min.js", "/js/liaisons.js", ) css = {'all': ("/css/liaisons.css", "/css/jquery-ui-themes/jquery-ui-1.8.2.custom.css")} def __init__(self, user, *args, **kwargs): self.user = user self.person = get_person_for_user(user) if kwargs.get('data', None): kwargs['data'].update({'person': self.person.pk}) super(LiaisonForm, self).__init__(*args, **kwargs) 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() self.fields['replyto'].initial = email and email[1] 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 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()[1] for i in organization.get_poc()]) def get_cc(self, from_entity, to_entity): 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]) def save(self, *args, **kwargs): liaison = super(LiaisonForm, self).save(*args, **kwargs) self.save_extra_fields(liaison) self.save_attachments(liaison) return liaison def save_extra_fields(self, liaison): now = datetime.datetime.now() liaison.submitted_date = now liaison.last_modified_date = now from_entity = self.get_from_entity() liaison.from_raw_body = from_entity.name liaison.from_raw_code = self.cleaned_data.get('from_field') organization = self.get_to_entity() liaison.to_body = organization.name liaison.to_poc = self.get_poc(organization) liaison.submitter_name, liaison.submitter_email = self.person.email() liaison.cc1 = self.get_cc(from_entity, organization) liaison.save() def save_attachments(self, instance): 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, ) class IncomingLiaisonForm(LiaisonForm): def set_from_field(self): if is_ietf_liaison_manager(self.user): sdos = SDOs.objects.all() else: sdo_managed = [i.sdo for i in self.person.liaisonmanagers_set.all()] sdo_authorized = [i.sdo for i in self.person.sdoauthorizedindividual_set.all()] sdos = set(sdo_managed).union(sdo_authorized) self.fields['from_field'].choices = [('sdo_%s' % i.pk, i.sdo_name) for i in sdos] 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): if self.user.groups.filter(name='Liaison_Manager'): return True return False def clean(self): if self.data.has_key('send') 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() 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_ietf_liaison_manager(self.user): self.fields['from_field'].choices = self.hm.get_all_incoming_entities() 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): 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): 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() 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: model = LiaisonDetail fields = ('from_raw_body', 'to_body', 'to_poc', 'cc1', 'last_modified_date', 'title', 'response_contact', 'technical_contact', 'purpose_text', 'body', 'deadline_date', 'purpose', 'replyto', ) def __init__(self, *args, **kwargs): super(EditLiaisonForm, self).__init__(*args, **kwargs) self.edit = True 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): now = datetime.datetime.now() liaison.last_modified_date = now liaison.from_raw_body = self.cleaned_data.get('from_field') liaison.to_body = self.cleaned_data.get('organization') liaison.to_poc = self.cleaned_data['to_poc'] liaison.cc1 = self.cleaned_data['cc1'] liaison.save() def liaison_form_factory(request, **kwargs): user = request.user force_incoming = 'incoming' in request.GET.keys() liaison = kwargs.pop('liaison', None) if liaison: return EditLiaisonForm(user, instance=liaison, **kwargs) if not force_incoming and can_add_outgoing_liaison(user): return OutgoingLiaisonForm(user, **kwargs) elif can_add_incoming_liaison(user): return IncomingLiaisonForm(user, **kwargs) return None