source: asadb/forms/views.py @ df88ee9

space-accessstablestagetest-hooks
Last change on this file since df88ee9 was 055a7e9, checked in by Alex Dehnert <adehnert@…>, 14 years ago

Allow selecting suspended groups elsewhere

  • Property mode set to 100644
File size: 16.8 KB
Line 
1import forms.models
2import groups.models
3import groups.views
4import settings
5
6from django.contrib.auth.decorators import user_passes_test, login_required, permission_required
7from django.views.generic import list_detail, ListView, DetailView
8from django.shortcuts import render_to_response, get_object_or_404
9from django.template import RequestContext
10from django.template import Context, Template
11from django.template.loader import get_template
12from django.http import Http404, HttpResponseRedirect, HttpResponse
13from django.core.urlresolvers import reverse
14from django.core.mail import EmailMessage, mail_admins
15from django.forms import Form
16from django.forms import ModelForm
17from django.forms import ModelChoiceField, ModelMultipleChoiceField
18from django.db import connection
19from django.db.models import Q, Count
20
21import csv
22import datetime
23import StringIO
24
25#################
26# GENERIC VIEWS #
27#################
28
29class SelectGroupForm(Form):
30    group = ModelChoiceField(queryset=groups.models.Group.objects.all())
31    def __init__(self, *args, **kwargs):
32        queryset = None
33        if 'queryset' in kwargs:
34            queryset = kwargs['queryset']
35            del kwargs['queryset']
36        super(SelectGroupForm, self).__init__(*args, **kwargs)
37        if queryset is not None:
38            self.fields["group"].queryset = queryset
39
40def select_group(request, url_name_after, pagename='homepage', queryset=None, ):
41    if request.method == 'POST': # If the form has been submitted...
42        # A form bound to the POST data
43        form = SelectGroupForm(request.POST, queryset=queryset, )
44        if form.is_valid(): # All validation rules pass
45            group = form.cleaned_data['group'].id
46            return HttpResponseRedirect(reverse(url_name_after, args=[group],)) # Redirect after POST
47    else:
48        form = SelectGroupForm(queryset=queryset, ) # An unbound form
49
50    context = {
51        'form':form,
52        'pagename':pagename,
53    }
54    return render_to_response('forms/select.html', context, context_instance=RequestContext(request), )
55
56#############################
57# FIRST-YEAR SUMMER MAILING #
58#############################
59
60@login_required
61def fysm_by_years(request, year, category, ):
62    if year is None: year = datetime.date.today().year
63    queryset = forms.models.FYSM.objects.filter(year=year).order_by('group__name')
64    category_obj = None
65    category_name = 'main'
66    if category != None:
67        category_obj = get_object_or_404(forms.models.FYSMCategory, slug=category)
68        category_name = category_obj.name
69        queryset = queryset.filter(categories=category_obj)
70    forms.models.FYSMView.record_metric(request=request, fysm=None, year=year, page=category_name, )
71    categories = forms.models.FYSMCategory.objects.all()
72    return list_detail.object_list(
73        request,
74        queryset=queryset,
75        template_name="fysm/fysm_listing.html",
76        template_object_name="fysm",
77        extra_context={
78            "year": year,
79            "pagename": "fysm",
80            "category": category_obj,
81            "categories": categories,
82        }
83    )
84
85@login_required
86def fysm_view(request, year, submission, ):
87    submit_obj = get_object_or_404(forms.models.FYSM, pk=submission,)
88    all = forms.models.FYSM.objects.only("id", "display_name", )
89    try:
90        prev = all.filter(display_name__lt=submit_obj.display_name).order_by("-display_name")[0]
91    except IndexError:
92        prev = None
93    try:
94        next = all.filter(display_name__gt=submit_obj.display_name).order_by("display_name")[0]
95    except IndexError:
96        next = None
97    forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page="detail", )
98    return list_detail.object_detail(
99        request,
100        forms.models.FYSM.objects,
101        object_id=submission,
102        template_name="fysm/fysm_detail.html",
103        template_object_name="fysm",
104        extra_context={
105            "year": year,
106            "pagename": "fysm",
107            "prev": prev,
108            "next": next,
109        },
110    )
111
112def fysm_link(request, year, link_type, submission, ):
113    submit_obj = get_object_or_404(forms.models.FYSM, pk=submission,)
114    if submit_obj.year != int(year):
115        raise Http404("Year mismatch: fysm.year='%s', request's year='%s'" % (submit_obj.year, year, ))
116    if link_type == 'join':
117        url = submit_obj.join_url
118    elif link_type == 'website':
119        url = submit_obj.website
120    else:
121        raise Http404("Unknown link type")
122    forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page=link_type, )
123    return HttpResponseRedirect(url)
124
125def select_group_fysm(request, ):
126    qobj = Q(activity_category__isnull = True) | ~(Q(activity_category__name='Dorm') | Q(activity_category__name='FSILG'))
127    queryset = groups.models.Group.active_groups.filter(qobj)
128    return select_group(
129        request,
130        url_name_after='fysm-manage',
131        pagename='fysm',
132        queryset=queryset,
133    )
134
135class FYSMRequestForm(ModelForm):
136    class Meta:
137        model = forms.models.FYSM
138        fields = (
139            'display_name',
140            'website',
141            'join_url',
142            'contact_email',
143            'description',
144            'logo',
145            'slide',
146            'tags',
147            'categories',
148        )
149
150@login_required
151def fysm_manage(request, group, ):
152    year = datetime.date.today().year
153    group_obj = get_object_or_404(groups.models.Group, pk=group)
154
155    initial = {}
156    try:
157        fysm_obj = forms.models.FYSM.objects.get(group=group_obj, year=year, )
158        print "Successfully found", fysm_obj.__dict__
159    except forms.models.FYSM.DoesNotExist:
160        fysm_obj = forms.models.FYSM()
161        fysm_obj.group = group_obj
162        fysm_obj.year = year
163        initial['display_name'] = group_obj.name
164        initial['year'] = year
165        initial['website'] = group_obj.website_url
166        initial['join_url'] = group_obj.website_url
167        initial['contact_email'] = group_obj.officer_email
168
169    if request.method == 'POST': # If the form has been submitted...
170        form = FYSMRequestForm(request.POST, request.FILES, instance=fysm_obj, ) # A form bound to the POST data
171
172        if form.is_valid(): # All validation rules pass
173            request_obj = form.save()
174
175            view_path = reverse('fysm-view', args=[year, request_obj.pk, ])
176            view_uri = '%s://%s%s' % (request.is_secure() and 'https' or 'http',
177                 request.get_host(), view_path)
178
179            # Send email
180            tmpl = get_template('fysm/update_email.txt')
181            ctx = Context({
182                'group': group_obj,
183                'fysm': fysm_obj,
184                'view_uri': view_uri,
185                'submitter': request.user,
186                'request': request,
187                'sender': "ASA FYSM team",
188            })
189            body = tmpl.render(ctx)
190            email = EmailMessage(
191                subject='FYSM entry for "%s" updated by "%s"' % (
192                    group_obj.name,
193                    request.user,
194                ),
195                body=body,
196                from_email='asa-fysm@mit.edu',
197                to=[group_obj.officer_email, request.user.email, ],
198                bcc=['asa-fysm-submissions@mit.edu', ]
199            )
200            email.send()
201            return HttpResponseRedirect(reverse('fysm-thanks', args=[fysm_obj.pk],)) # Redirect after POST
202
203    else:
204        form = FYSMRequestForm(instance=fysm_obj, initial=initial, ) # An unbound form
205
206    context = {
207        'group':group_obj,
208        'fysm':fysm_obj,
209        'form':form,
210        'categories':forms.models.FYSMCategory.objects.all(),
211        'pagename':'fysm',
212    }
213    return render_to_response('fysm/submit.html', context, context_instance=RequestContext(request), )
214
215
216def fysm_thanks(request, fysm, ):
217    year = datetime.date.today().year
218    fysm_obj = get_object_or_404(forms.models.FYSM, pk=fysm)
219
220    context = {
221        'group':fysm_obj.group,
222        'fysm':fysm_obj,
223        'pagename':'fysm',
224    }
225    return render_to_response('fysm/thanks.html', context, context_instance=RequestContext(request), )
226
227#####################
228# Membership update #
229#####################
230
231membership_update_qs = groups.models.Group.objects.filter(group_status__slug__in=['active', 'suspended', ])
232
233class Form_GroupMembershipUpdate(ModelForm):
234    group = ModelChoiceField(queryset=membership_update_qs)
235
236    def __init__(self, *args, **kwargs):
237        super(Form_GroupMembershipUpdate, self).__init__(*args, **kwargs)
238        self.fields['no_hazing'].required = True
239
240    class Meta:
241        model = forms.models.GroupMembershipUpdate
242        fields = [
243            'group',
244            'updater_title',
245            'group_email',
246            'officer_email',
247            'email_preface',
248            'no_hazing',
249            'no_discrimination',
250            'membership_definition',
251            'num_undergrads',
252            'num_grads',
253            'num_alum',
254            'num_other_affiliate',
255            'num_other',
256            'membership_list',
257        ]
258
259@login_required
260def group_membership_update(request, ):
261    year = datetime.date.today().year
262
263    initial = {
264    }
265    update_obj = forms.models.GroupMembershipUpdate()
266    update_obj.update_time  = datetime.datetime.now()
267    update_obj.updater_name = request.user.username
268
269    confirm_path = reverse('membership-confirm', )
270    confirm_uri = '%s://%s%s' % (request.is_secure() and 'https' or 'http',
271         request.get_host(), confirm_path)
272
273    if request.method == 'POST': # If the form has been submitted...
274        form = Form_GroupMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data
275
276        if form.is_valid(): # All validation rules pass
277            request_obj = form.save()
278            group_obj = request_obj.group
279
280
281            # Send email
282            tmpl = get_template('membership/anti-hazing.txt')
283            ctx = Context({
284                'update': request_obj,
285                'group': group_obj,
286                'submitter': request.user,
287            })
288            body = tmpl.render(ctx)
289            email = EmailMessage(
290                subject='Anti-Hazing and Non-Discrimination Acknowledgement for %s' % (
291                    group_obj.name,
292                ),
293                body=body,
294                from_email=request.user.email,
295                to=[request_obj.group_email, ],
296                cc=[request_obj.officer_email, ],
297                bcc=['asa-db-outgoing@mit.edu', ],
298            )
299            email.send()
300
301            # Send email
302            tmpl = get_template('membership/submit-confirm-email.txt')
303            ctx = Context({
304                'update': request_obj,
305                'group': group_obj,
306                'submitter': request.user,
307                'confirm_uri': confirm_uri,
308            })
309            body = tmpl.render(ctx)
310            email = EmailMessage(
311                subject='ASA Membership Information for %s' % (
312                    group_obj.name,
313                ),
314                body=body,
315                from_email=request.user.email,
316                to=[request_obj.officer_email, ],
317                bcc=['asa-db-outgoing@mit.edu', ],
318            )
319            email.send()
320
321            return HttpResponseRedirect(reverse('membership-thanks', )) # Redirect after POST
322
323    else:
324        form = Form_GroupMembershipUpdate(initial=initial, ) # An unbound form
325
326    context = {
327        'form':form,
328        'confirm_uri': confirm_uri,
329        'pagename':'groups',
330    }
331    return render_to_response('membership/update.html', context, context_instance=RequestContext(request), )
332
333class Form_PersonMembershipUpdate(ModelForm):
334    groups = ModelMultipleChoiceField(queryset=membership_update_qs)
335    class Meta:
336        model = forms.models.PersonMembershipUpdate
337        fields = [
338            'groups',
339        ]
340
341@login_required
342def person_membership_update(request, ):
343    year = datetime.date.today().year
344
345    initial = {
346    }
347    cycle = forms.models.GroupConfirmationCycle.latest()
348    try:
349        update_obj = forms.models.PersonMembershipUpdate.objects.get(
350            username=request.user.username,
351            deleted__isnull=True,
352            cycle=cycle,
353        )
354        selected_groups = update_obj.groups.all()
355        print "Got update"
356    except forms.models.PersonMembershipUpdate.DoesNotExist:
357        update_obj = forms.models.PersonMembershipUpdate()
358        update_obj.update_time  = datetime.datetime.now()
359        update_obj.username = request.user.username
360        update_obj.cycle = cycle
361        selected_groups = []
362
363    accounts = groups.models.AthenaMoiraAccount
364    try:
365        person = accounts.active_accounts.get(username=request.user.username)
366        if person.is_student():
367            update_obj.valid = forms.models.VALID_AUTOVALIDATED
368        else:
369            update_obj.valid = forms.models.VALID_AUTOREJECTED
370    except accounts.DoesNotExist:
371        pass
372        update_obj.valid = forms.models.VALID_AUTOREJECTED
373
374    update_obj.save()
375
376    filterset = groups.views.GroupFilter(request.GET, membership_update_qs)
377    filtered_groups = filterset.qs.all()
378    show_filtered_groups = ('search' in request.GET)
379
380    message = ""
381    message_type = "info"
382
383    if request.method == 'POST' and 'add-remove' in request.POST:
384        group = groups.models.Group.objects.get(id=request.POST['group'])
385        if request.POST['action'] == 'remove':
386            if group in update_obj.groups.all():
387                update_obj.groups.remove(group)
388                message = "You have been successfully removed from %s." % (group, )
389            else:
390                message = "Sorry, but you're not in %s." % (group, )
391                message_type = "warn"
392        elif request.POST['action'] == 'add':
393            if group in update_obj.groups.all():
394                message = "Sorry, but you're already in %s." % (group, )
395                message_type = "warn"
396            else:
397                update_obj.groups.add(group)
398                message = "You have been successfully added to %s." % (group, )
399        else:
400            message = "Uh, somehow you tried to do something besides adding and removing..."
401            message_type = "alert"
402
403    if request.method == 'POST' and 'list' in request.POST: # If the form has been submitted...
404        form = Form_PersonMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data
405
406        if form.is_valid(): # All validation rules pass
407            request_obj = form.save()
408            message = "Update saved"
409
410    else:
411        form = Form_PersonMembershipUpdate(initial=initial, instance=update_obj, ) # An unbound form
412
413    context = {
414        'form':form,
415        'filter':filterset,
416        'show_filtered_groups':show_filtered_groups,
417        'filtered_groups':filtered_groups,
418        'member_groups':selected_groups,
419        'message': message,
420        'message_type': message_type,
421        'pagename':'groups',
422    }
423    return render_to_response('membership/confirm.html', context, context_instance=RequestContext(request), )
424
425
426class View_GroupMembershipList(ListView):
427    context_object_name = "group_list"
428    template_name = "membership/submitted.html"
429
430    def get_queryset(self):
431        group_updates = forms.models.GroupMembershipUpdate.objects.all()
432        group_updates = group_updates.filter(
433            group__personmembershipupdate__deleted__isnull=True,
434            group__personmembershipupdate__valid__gt=0,
435        )
436        group_updates = group_updates.annotate(num_confirms=Count('group__personmembershipupdate'))
437        #print len(list(group_updates))
438        #for query in connection.queries: print query
439        return group_updates
440
441
442@permission_required('groups.view_group_private_info')
443def group_confirmation_issues(request, ):
444    active_groups = groups.models.Group.active_groups
445    group_updates = forms.models.GroupMembershipUpdate.objects.all()
446    people_confirmations = forms.models.PersonMembershipUpdate.objects.filter(
447        deleted__isnull=True,
448        valid__gt=0,
449    )
450
451    buf = StringIO.StringIO()
452    output = csv.writer(buf)
453    output.writerow(['group_id', 'group_name', 'issue', 'num_confirm', 'officer_email', ])
454
455    q_present = Q(id__in=group_updates.values('group'))
456    missing_groups = active_groups.filter(~q_present)
457    #print len(list(group_updates))
458    for group in missing_groups:
459        num_confirms = len(people_confirmations.filter(groups=group))
460        output.writerow([
461            group.id,
462            group.name,
463            'unsubmitted',
464            num_confirms,
465            group.officer_email,
466        ])
467
468    for group_update in group_updates:
469        group = group_update.group
470        num_confirms = len(people_confirmations.filter(groups=group))
471        if num_confirms < 5:
472            output.writerow([
473                group.id,
474                group.name,
475                'confirmations',
476                num_confirms,
477                group.officer_email,
478            ])
479
480
481    return HttpResponse(buf.getvalue(), mimetype='text/plain', )
Note: See TracBrowser for help on using the repository browser.