Changeset 2919697


Ignore:
Timestamp:
Oct 23, 2011, 3:36:38 PM (14 years ago)
Author:
Alex Dehnert <adehnert@…>
Branches:
master, space-access, stable, stage, test-hooks
Children:
86d9174
Parents:
96c5790
git-author:
Alex Dehnert <adehnert@…> (10/23/11 05:59:20)
git-committer:
Alex Dehnert <adehnert@…> (10/23/11 15:36:38)
Message:

More work on group recognition forms

Location:
asadb
Files:
7 added
1 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • asadb/groups/admin.py

    r3107c52 r2919697  
    2727admin.site.register(groups.models.Group, GroupAdmin)
    2828
     29
     30class Admin_GroupStartup(VersionAdmin):
     31    list_display = (
     32        'id',
     33        'group',
     34        'stage',
     35        'president_kerberos',
     36        'create_officer_list',
     37        'create_group_list',
     38        'create_athena_locker',
     39    )
     40    list_display_links = ('id', 'group', )
     41    search_fields = [ 'group__name', 'group__abbreviation', 'president_kerberos', ]
     42admin.site.register(groups.models.GroupStartup, Admin_GroupStartup)
    2943
    3044class Admin_GroupNote(VersionAdmin):
  • asadb/groups/models.py

    r3275ab1 r2919697  
    9999
    100100
     101GROUP_STARTUP_STAGE_SUBMITTED = 10
     102GROUP_STARTUP_STAGE_APPROVED = 20
     103GROUP_STARTUP_STAGE_REJECTED = -10
     104GROUP_STARTUP_STAGE = (
     105    (GROUP_STARTUP_STAGE_SUBMITTED,     'submitted'),
     106    (GROUP_STARTUP_STAGE_APPROVED,      'approved'),
     107    (GROUP_STARTUP_STAGE_REJECTED,      'rejected'),
     108)
     109
     110class GroupStartup(models.Model):
     111    group = models.ForeignKey(Group)
     112    stage = models.IntegerField(choices=GROUP_STARTUP_STAGE)
     113    create_officer_list = models.BooleanField()
     114    create_group_list = models.BooleanField()
     115    create_athena_locker = models.BooleanField()
     116    president_name = models.CharField(max_length=50)
     117    president_kerberos = models.CharField(max_length=8)
     118    treasurer_name = models.CharField(max_length=50)
     119    treasurer_kerberos = models.CharField(max_length=8)
     120
     121
    101122class GroupNote(models.Model):
    102123    author = models.CharField(max_length=30, ) # match Django username field
  • asadb/groups/urls.py

    rb04e142 r2919697  
    1313    (r'^(?P<pk>\d+)/', include(group_patterns, ), ),
    1414    url(r'^$', groups.views.GroupListView.as_view(), name='list', ),
    15     url(r'^create/(?P<status>\w+)?$', groups.views.create_group, name='create', ),
     15    url(r'^startup/$', groups.views.startup_form, name='startup', ),
     16    url(r'^startup/review/$', groups.views.GroupStartupListView.as_view(), name='startup-list', ),
     17    url(r'^startup/review/(?P<pk>\d+)$', groups.views.recognize_normal_group, name='startup-recognize', ),
     18    url(r'^recognize/nge/$', groups.views.recognize_nge, name='recognize-nge', ),
    1619    url(r'^search/$', groups.views.search_groups, name='search', ),
    1720    url(r'^recent_changes/$', groups.views.GroupHistoryView.as_view(), name='manage-history', ),
  • asadb/groups/views.py

    rb04e142 r2919697  
    1717from django.core.urlresolvers import reverse
    1818from django.core.mail import EmailMessage, mail_admins
    19 from django.forms import CharField, ModelChoiceField, MultipleChoiceField
    20 from django.forms import Form, ModelForm
     19from django import forms
    2120from django.forms import ValidationError
    2221from django.db import connection
     
    189188    return render_to_response('groups/group_change_main.html', context, context_instance=RequestContext(request), )
    190189
     190
     191##################
     192# GROUP CREATION #
     193##################
     194
    191195def validate_athena(username, student=False, ):
    192196    try:
     
    197201        raise ValidationError('This must be a valid Athena username.')
    198202
     203
    199204class GroupCreateForm(form_utils.forms.BetterModelForm):
    200     create_which = MultipleChoiceField(
    201         choices=[
    202             ('officer_email', 'officer list', ),
    203             ('group_email', 'group list', ),
    204             ('athena_locker', 'Athena locker', ),
    205         ],
    206     )
    207 
    208     president = CharField(min_length=3, max_length=8, )
    209     treasurer = CharField(min_length=3, max_length=8, )
     205    create_officer_list = forms.BooleanField(required=False)
     206    create_group_list = forms.BooleanField(required=False)
     207    create_athena_locker = forms.BooleanField(required=False)
     208
     209    president_name = forms.CharField(max_length=50, )
     210    president_kerberos = forms.CharField(min_length=3, max_length=8, )
     211    treasurer_name = forms.CharField(max_length=50)
     212    treasurer_kerberos = forms.CharField(min_length=3, max_length=8, )
    210213    def clean_president(self, ):
    211         username = self.cleaned_data['president']
     214        username = self.cleaned_data['president_kerberos']
    212215        validate_athena(username, True, )
    213216        return username
    214217
    215218    def clean_treasurer(self, ):
    216         username = self.cleaned_data['treasurer']
     219        username = self.cleaned_data['treasurer_kerberos']
    217220        validate_athena(username, True, )
    218221        return username
     
    222225            ('basic', {
    223226                'legend': 'Basic Information',
    224                 'fields': ['name', 'abbreviation', 'activity_category', 'description', ],
     227                'fields': ['name', 'abbreviation', 'description', ],
    225228            }),
    226229            ('officers', {
    227230                'legend': 'Officers',
    228                 'fields': ['president', 'treasurer', ],
     231                'fields': ['president_name', 'president_kerberos', 'treasurer_name', 'treasurer_kerberos', ],
     232            }),
     233            ('type', {
     234                'legend': 'Type',
     235                'fields': ['activity_category', 'group_class', 'group_funding', ],
    229236            }),
    230237            ('technical', {
    231238                'legend': 'Technical Information',
    232                 'fields': ['officer_email', 'group_email', 'athena_locker', 'create_which', ],
    233             }),
    234             ('Category', {
    235                 'legend': 'Category',
    236                 'fields': ['group_status', 'group_class', ],
     239                'fields': [
     240                    'officer_email', 'create_officer_list',
     241                    'group_email', 'create_group_list',
     242                    'athena_locker', 'create_athena_locker',
     243                ],
    237244            }),
    238245            ('financial', {
    239246                'legend': 'Financial Information',
    240                 'fields': ['group_funding', 'main_account_id', 'funding_account_id', ],
    241             }),
    242             ('more-info', {
    243                 'legend': 'Additional Information',
     247                'fields': ['main_account_id', 'funding_account_id', ],
     248            }),
     249            ('constitution', {
     250                'legend': 'Constitution',
    244251                'fields': ['constitution_url', ],
    245252            }),
     
    248255
    249256
     257class GroupCreateNgeForm(GroupCreateForm):
     258    def __init__(self, *args, **kwargs):
     259        super(GroupCreateNgeForm, self).__init__(*args, **kwargs)
     260        self.fields['treasurer_name'].required = False
     261        self.fields['treasurer_kerberos'].required = False
     262
     263    class Meta(GroupCreateForm.Meta):
     264        fieldsets = filter(
     265            lambda fieldset: fieldset[0] not in ['financial', ],
     266            GroupCreateForm.Meta.fieldsets
     267        )
     268
     269
     270class GroupCreateStartupForm(GroupCreateForm):
     271    def __init__(self, *args, **kwargs):
     272        super(GroupCreateStartupForm, self).__init__(*args, **kwargs)
     273        self.fields['activity_category'].required = True
     274        self.fields['constitution_url'].required = True
     275        self.fields['constitution_url'].help_text = "Please put a copy of your finalized constitution on a publicly-accessible website (e.g. your group's, or your own, Public folder), and link to it in the box above."
     276
     277    class Meta(GroupCreateForm.Meta):
     278        fieldsets = filter(
     279            lambda fieldset: fieldset[0] not in ['financial', ],
     280            GroupCreateForm.Meta.fieldsets
     281        )
     282
     283def create_group_get_emails(group, group_startup, officer_emails, ):
     284    # Figure out all the accounts mail parameters
     285    accounts_count = 0
     286    create_officer_list = False
     287    if group_startup.create_officer_list and group.officer_email:
     288        create_officer_list = True
     289        accounts_count += 1
     290    create_group_list = False
     291    if group_startup.create_group_list and group.group_email:
     292        create_group_list = True
     293        accounts_count += 1
     294    create_athena_locker = False
     295    if group_startup.create_athena_locker and group.athena_locker:
     296        create_athena_locker = True
     297        accounts_count += 1
     298    officer_list, _, officer_domain = group.officer_email.partition('@')
     299    group_list, _, group_domain = group.group_email.partition('@')
     300
     301    # Fill out the Context
     302    mail_context = Context({
     303        'group': group,
     304        'group_startup': group_startup,
     305        'create_officer_list': create_officer_list,
     306        'create_group_list': create_group_list,
     307        'create_athena_locker': create_athena_locker,
     308        'officer_list': officer_list,
     309        'group_list': group_list,
     310        'officer_emails': officer_emails,
     311    })
     312
     313    # Welcome mail
     314    welcome_mail = email_from_template(
     315        tmpl='groups/diffs/new-group-announce.txt',
     316        context=mail_context,
     317        subject='ASA Group Recognition: %s' % (group.name, ),
     318        to=officer_emails,
     319        cc=['asa-new-group-announce@mit.edu'],
     320        from_email='asa-exec@mit.edu',
     321    )
     322
     323    # Accounts mail
     324    if accounts_count > 0:
     325        accounts_mail = email_from_template(
     326            tmpl='groups/diffs/new-group-accounts.txt',
     327            context=mail_context,
     328            subject='New Student Activity: %s' % (group.name, ),
     329            to=['accounts@mit.edu'],
     330            cc=officer_emails+['asa-admin@mit.edu'],
     331            from_email='asa-admin@mit.edu',
     332        )
     333        # XXX: Handle this better
     334        if officer_domain != 'mit.edu' or (create_group_list and group_domain != 'mit.edu'):
     335            accounts_mail.to = ['asa-groups@mit.edu']
     336            accounts_mail.cc = ['asa-db@mit.edu']
     337            accounts_mail.subject = "ERROR: " + accounts_mail.subject
     338            accounts_mail.body = "Bad domain on officer or group list\n\n" + accounts_mail.body
     339
     340    else:
     341        accounts_mail = None
     342    return welcome_mail, accounts_mail
     343
     344def create_group_officers(group, formdata, ):
     345    officer_emails = [ ]
     346    for officer in ('president', 'treasurer', ):
     347        username = formdata[officer+'_kerberos']
     348        if username:
     349            groups.models.OfficeHolder(
     350                person=username,
     351                role=groups.models.OfficerRole.objects.get(slug=officer),
     352                group=group,
     353            ).save()
     354            officer_emails.append('%s@mit.edu' % (formdata[officer+'_kerberos'], ))
     355    return officer_emails
     356
    250357@permission_required('groups.add_group')
    251 def create_group(request, status=None,):
    252     if not status: status = 'active'
    253     groupstatus = get_object_or_404(groups.models.GroupStatus, slug=status)
    254    
     358def recognize_nge(request, ):
    255359    msg = None
    256360
    257361    initial = {
    258         'create_which': ['officer_email', 'group_email', 'athena_locker', ],
     362        'create_officer_list': False,
     363        'create_group_list': False,
     364        'create_athena_locker': True,
    259365    }
    260366    group = groups.models.Group()
    261     group.group_status = groupstatus
     367    group.group_status = groups.models.GroupStatus.objects.get(slug='nge', )
    262368    group.recognition_date  = datetime.datetime.now()
    263369    if request.method == 'POST': # If the form has been submitted...
    264370        # A form bound to the POST data
    265         form = GroupCreateForm(
     371        form = GroupCreateNgeForm(
    266372            request.POST, request.FILES,
    267373            initial=initial,
     
    270376
    271377        if form.is_valid(): # All validation rules pass
    272             # Basic setup
    273378            group.set_updater(request.user)
    274379            form.save()
    275 
    276             # Officers
    277             groups.models.OfficeHolder(
    278                 person=form.cleaned_data['president'],
    279                 role=groups.models.OfficerRole.objects.get(slug='president'),
    280                 group=group,
    281             ).save()
    282             groups.models.OfficeHolder(
    283                 person=form.cleaned_data['treasurer'],
    284                 role=groups.models.OfficerRole.objects.get(slug='treasurer'),
    285                 group=group,
    286             ).save()
    287             officer_emails = [
    288                 '%s@mit.edu' % (form.cleaned_data['president'], ),
    289                 '%s@mit.edu' % (form.cleaned_data['treasurer'], ),
    290             ]
    291 
    292             # Sending mail
    293             mail_context = Context({
    294                 'group': group,
    295                 'formdata': form.cleaned_data,
    296             })
    297 
    298             # Welcome mail
    299             email_from_template(
    300                 tmpl='groups/diffs/new-group-announce.txt',
    301                 context=mail_context,
    302                 subject='ASA Group Recognition: %s' % (group.name, ),
    303                 to=officer_emails,
    304                 cc=['asa-new-group-announce@mit.edu'],
    305                 from_email='asa-exec@mit.edu',
    306             ).send()
    307             if len(form.cleaned_data['create_which']) > 0:
    308                 email_from_template(
    309                     tmpl='groups/diffs/new-group-accounts.txt',
    310                     context=mail_context,
    311                     subject='New Student Activity: %s' % (group.name, ),
    312                     to=['accounts@mit.edu'],
    313                     cc=officer_emails+['asa-admin@mit.edu'],
    314                     from_email='asa-admin@mit.edu',
    315                 ).send()
    316 
     380            officer_emails = create_group_officers(group, form.cleaned_data, )
    317381
    318382            return redirect(reverse('groups:group-detail', args=[group.pk]))
     
    321385
    322386    else:
    323         form = GroupCreateForm(initial=initial, instance=group, ) # An unbound form
     387        form = GroupCreateNgeForm(initial=initial, instance=group, ) # An unbound form
    324388
    325389    context = {
     
    328392        'pagename':   'groups',
    329393    }
    330     return render_to_response('groups/group_create.html', context, context_instance=RequestContext(request), )
     394    return render_to_response('groups/create/nge.html', context, context_instance=RequestContext(request), )
     395
     396def startup_form(request, ):
     397    msg = None
     398
     399    initial = {
     400        'create_officer_list': True,
     401        'create_group_list': True,
     402        'create_athena_locker': True,
     403    }
     404    group = groups.models.Group()
     405    group.group_status = groups.models.GroupStatus.objects.get(slug='applying', )
     406    group.recognition_date  = datetime.datetime.now()
     407    if request.method == 'POST': # If the form has been submitted...
     408        # A form bound to the POST data
     409        form = GroupCreateStartupForm(
     410            request.POST, request.FILES,
     411            initial=initial,
     412            instance=group,
     413        )
     414
     415        if form.is_valid(): # All validation rules pass
     416            group.set_updater(request.user)
     417            form.save()
     418
     419            group_startup = groups.models.GroupStartup()
     420            group_startup.group = group
     421            group_startup.stage = groups.models.GROUP_STARTUP_STAGE_SUBMITTED
     422
     423            group_startup.create_officer_list = form.cleaned_data['create_officer_list']
     424            group_startup.create_group_list = form.cleaned_data['create_group_list']
     425            group_startup.create_athena_locker = form.cleaned_data['create_athena_locker']
     426
     427            group_startup.president_name = form.cleaned_data['president_name']
     428            group_startup.president_kerberos = form.cleaned_data['president_kerberos']
     429            group_startup.treasurer_name = form.cleaned_data['treasurer_name']
     430            group_startup.treasurer_kerberos = form.cleaned_data['treasurer_kerberos']
     431
     432            group_startup.save()
     433
     434            context = {
     435                'group':  group,
     436                'pagename':   'groups',
     437            }
     438            return render_to_response('groups/create/startup_thanks.html', context, context_instance=RequestContext(request), )
     439        else:
     440            msg = "Validation failed. See below for details."
     441
     442    else:
     443        form = GroupCreateStartupForm(initial=initial, instance=group, ) # An unbound form
     444
     445    context = {
     446        'form':  form,
     447        'msg':   msg,
     448        'pagename':   'groups',
     449    }
     450    return render_to_response('groups/create/startup.html', context, context_instance=RequestContext(request), )
     451
     452class GroupRecognitionForm(forms.Form):
     453    test = forms.BooleanField()
     454
     455@permission_required('groups.add_group')
     456def recognize_normal_group(request, pk, ):
     457    group_startup = get_object_or_404(groups.models.GroupStartup, pk=pk, )
     458    group = group_startup.group
     459
     460    context = {
     461        'startup': group_startup,
     462        'group': group,
     463        'pagename' : 'groups',
     464    }
     465
     466    if group.group_status.slug != 'applying':
     467        return render_to_response('groups/create/err.not-applying.html', context, context_instance=RequestContext(request), )
     468    if group_startup.stage != groups.models.GROUP_STARTUP_STAGE_SUBMITTED:
     469        return render_to_response('groups/create/err.not-applying.html', context, context_instance=RequestContext(request), )
     470
     471    context['msg'] = ""
     472    if request.method == 'POST':
     473        if 'approve' in request.POST:
     474            group_startup.stage = groups.models.GROUP_STARTUP_STAGE_APPROVED
     475            group_startup.save()
     476
     477            group.group_status = groups.models.GroupStatus.objects.get(slug='active')
     478            group.constitution_url = ""
     479            group.recognition_date = datetime.date.today()
     480            group.set_updater(request.user)
     481
     482            group.save()
     483            officer_emails = create_group_officers(group, group_startup.__dict__, )
     484            welcome_mail, accounts_mail = create_group_get_emails(group, group_startup, officer_emails, )
     485            welcome_mail.send()
     486            if accounts_mail:
     487                accounts_mail.send()
     488            context['msg'] = 'Group approved.'
     489            context['msg_type'] = 'info'
     490        elif 'reject' in request.POST:
     491            group_startup.stage = groups.models.GROUP_STARTUP_STAGE_REJECTED
     492            group_startup.save()
     493            group.group_status = groups.models.GroupStatus.objects.get(slug='derecognized')
     494            group.save()
     495            note = groups.models.GroupNote(
     496                author=request.user.username,
     497                body="Group rejected during recognition process.",
     498                acl_read_group=True,
     499                acl_read_offices=True,
     500                group=group,
     501            ).save()
     502            context['msg'] = 'Group rejected.'
     503            context['msg_type'] = 'info'
     504        else:
     505            context['disp_form'] = True
     506    else:
     507        context['disp_form'] = True
     508
     509    return render_to_response('groups/create/startup_review.html', context, context_instance=RequestContext(request), )
     510
     511class GroupStartupListView(ListView):
     512    model = groups.models.GroupStartup
     513    template_object_name = 'startup'
     514
     515    def get_queryset(self, ):
     516        qs = super(GroupStartupListView, self).get_queryset()
     517        qs = qs.filter(stage=groups.models.GROUP_STARTUP_STAGE_SUBMITTED)
     518        qs = qs.select_related('group')
     519        return qs
     520
     521    def get_context_data(self, **kwargs):
     522        context = super(GroupStartupListView, self).get_context_data(**kwargs)
     523        context['pagename'] = 'groups'
     524        return context
     525
    331526
    332527##################
  • asadb/template/groups/diffs/new-group-accounts.txt

    rb04e142 r2919697  
    88Please create the following resources:
    99
    10 {% if "athena_locker" in formdata.create_which and group.athena_locker %}
     10{% if create_athena_locker %}
    1111  Activity Locker under /afs/athena/activity/: {{group.athena_locker}}
    12       User owner  : {{formdata.president}}
    13       Group owner : {{group.officer_email}}
     12      User owner  : {{group_startup.president_kerberos}}
     13      Group owner : {{officer_list}}
    1414
    15 {% endif %}{% if "officer_email" in formdata.create_which %}
    16   List : {{group.officer_email}}
     15{% endif %}{% if create_officer_list %}
     16  List : {{officer_list}}
    1717      Group         : Yes
    1818      Mailing List  : Yes
    1919      Administrator : self
    20       Members       : {{formdata.president}}
     20      Members       : {{group_startup.president_kerberos}}
    2121
    22 {% endif %}{% if "group_email" in formdata.create_which and group.group_email %}
    23   List : {{group.group_email}}
     22{% endif %}{% if create_group_list %}
     23  List : {{group_list}}
    2424      Group         : Yes
    2525      Mailing List  : Yes
    26       Administrator : {{group.officer_email}}
    27       Members       : {{formdata.president}}
     26      Administrator : {{officer_list}}
     27      Members       : {{group_startup.president_kerberos}}
    2828{% endif %}
    2929
    3030Please send confirmation of the completion to
    31    {{formdata.president}}
     31   {{officer_emails|join:", "}}
    3232and
    3333   asa-admin@mit.edu
Note: See TracChangeset for help on using the changeset viewer.