source: asadb/forms/views.py @ e1f5425

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

Add report on group activity confirmation problems

  • Property mode set to 100644
File size: 17.2 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
231class Form_GroupMembershipUpdate(ModelForm):
232    group = ModelChoiceField(queryset=groups.models.Group.active_groups.all())
233
234    def __init__(self, *args, **kwargs):
235        super(Form_GroupMembershipUpdate, self).__init__(*args, **kwargs)
236        self.fields['no_hazing'].required = True
237
238    class Meta:
239        model = forms.models.GroupMembershipUpdate
240        fields = [
241            'group',
242            'updater_title',
243            'group_email',
244            'officer_email',
245            'email_preface',
246            'no_hazing',
247            'no_discrimination',
248            'membership_definition',
249            'num_undergrads',
250            'num_grads',
251            'num_alum',
252            'num_other_affiliate',
253            'num_other',
254            'membership_list',
255        ]
256
257@login_required
258def group_membership_update(request, ):
259    year = datetime.date.today().year
260
261    initial = {
262    }
263    update_obj = forms.models.GroupMembershipUpdate()
264    update_obj.update_time  = datetime.datetime.now()
265    update_obj.updater_name = request.user.username
266
267    confirm_path = reverse('membership-confirm', )
268    confirm_uri = '%s://%s%s' % (request.is_secure() and 'https' or 'http',
269         request.get_host(), confirm_path)
270
271    if request.method == 'POST': # If the form has been submitted...
272        form = Form_GroupMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data
273
274        if form.is_valid(): # All validation rules pass
275            request_obj = form.save()
276            group_obj = request_obj.group
277
278
279            # Send email
280            tmpl = get_template('membership/anti-hazing.txt')
281            ctx = Context({
282                'update': request_obj,
283                'group': group_obj,
284                'submitter': request.user,
285            })
286            body = tmpl.render(ctx)
287            email = EmailMessage(
288                subject='Anti-Hazing and Non-Discrimination Acknowledgement for %s' % (
289                    group_obj.name,
290                ),
291                body=body,
292                from_email=request.user.email,
293                to=[request_obj.group_email, ],
294                cc=[request_obj.officer_email, ],
295                bcc=['asa-db-outgoing@mit.edu', ],
296            )
297            email.send()
298
299            # Send email
300            tmpl = get_template('membership/submit-confirm-email.txt')
301            ctx = Context({
302                'update': request_obj,
303                'group': group_obj,
304                'submitter': request.user,
305                'confirm_uri': confirm_uri,
306            })
307            body = tmpl.render(ctx)
308            email = EmailMessage(
309                subject='ASA Membership Information for %s' % (
310                    group_obj.name,
311                ),
312                body=body,
313                from_email=request.user.email,
314                to=[request_obj.officer_email, ],
315                bcc=['asa-db-outgoing@mit.edu', ],
316            )
317            email.send()
318
319            return HttpResponseRedirect(reverse('membership-thanks', )) # Redirect after POST
320
321    else:
322        form = Form_GroupMembershipUpdate(initial=initial, ) # An unbound form
323
324    context = {
325        'form':form,
326        'confirm_uri': confirm_uri,
327        'pagename':'groups',
328    }
329    return render_to_response('membership/update.html', context, context_instance=RequestContext(request), )
330
331class Form_PersonMembershipUpdate(ModelForm):
332    groups = ModelMultipleChoiceField(queryset=groups.models.Group.active_groups.all())
333    class Meta:
334        model = forms.models.PersonMembershipUpdate
335        fields = [
336            'groups',
337        ]
338
339@login_required
340def person_membership_update(request, ):
341    year = datetime.date.today().year
342
343    initial = {
344    }
345    cycle = forms.models.GroupConfirmationCycle.latest()
346    try:
347        update_obj = forms.models.PersonMembershipUpdate.objects.get(
348            username=request.user.username,
349            deleted__isnull=True,
350            cycle=cycle,
351        )
352        selected_groups = update_obj.groups.all()
353        print "Got update"
354    except forms.models.PersonMembershipUpdate.DoesNotExist:
355        update_obj = forms.models.PersonMembershipUpdate()
356        update_obj.update_time  = datetime.datetime.now()
357        update_obj.username = request.user.username
358        update_obj.cycle = cycle
359        selected_groups = []
360
361    accounts = groups.models.AthenaMoiraAccount
362    try:
363        person = accounts.active_accounts.get(username=request.user.username)
364        if person.is_student():
365            update_obj.valid = forms.models.VALID_AUTOVALIDATED
366        else:
367            update_obj.valid = forms.models.VALID_AUTOREJECTED
368    except accounts.DoesNotExist:
369        pass
370        update_obj.valid = forms.models.VALID_AUTOREJECTED
371
372    update_obj.save()
373
374    qs = groups.models.Group.active_groups
375    filterset = groups.views.GroupFilter(request.GET, qs)
376    filtered_groups = filterset.qs.all()
377    show_filtered_groups = ('search' in request.GET)
378
379    message = ""
380    message_type = "info"
381
382    if request.method == 'POST' and 'add-remove' in request.POST:
383        group = groups.models.Group.objects.get(id=request.POST['group'])
384        if request.POST['action'] == 'remove':
385            if group in update_obj.groups.all():
386                update_obj.groups.remove(group)
387                message = "You have been successfully removed from %s." % (group, )
388            else:
389                message = "Sorry, but you're not in %s." % (group, )
390                message_type = "warn"
391        elif request.POST['action'] == 'add':
392            if group in update_obj.groups.all():
393                message = "Sorry, but you're already in %s." % (group, )
394                message_type = "warn"
395            else:
396                update_obj.groups.add(group)
397                message = "You have been successfully added to %s." % (group, )
398        else:
399            message = "Uh, somehow you tried to do something besides adding and removing..."
400            message_type = "alert"
401
402    if request.method == 'POST' and 'list' in request.POST: # If the form has been submitted...
403        form = Form_PersonMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data
404
405        if form.is_valid(): # All validation rules pass
406            request_obj = form.save()
407            message = "Update saved"
408
409    else:
410        form = Form_PersonMembershipUpdate(initial=initial, instance=update_obj, ) # An unbound form
411
412    context = {
413        'form':form,
414        'filter':filterset,
415        'show_filtered_groups':show_filtered_groups,
416        'filtered_groups':filtered_groups,
417        'member_groups':selected_groups,
418        'message': message,
419        'message_type': message_type,
420        'pagename':'groups',
421    }
422    return render_to_response('membership/confirm.html', context, context_instance=RequestContext(request), )
423
424
425class View_GroupMembershipList(ListView):
426    context_object_name = "group_list"
427    template_name = "membership/submitted.html"
428
429    def get_queryset(self):
430        group_updates = forms.models.GroupMembershipUpdate.objects.all()
431        group_updates = group_updates.filter(
432            group__personmembershipupdate__deleted__isnull=True,
433            group__personmembershipupdate__valid__gt=0,
434        )
435        group_updates = group_updates.annotate(num_confirms=Count('group__personmembershipupdate'))
436        #print len(list(group_updates))
437        #for query in connection.queries: print query
438        return group_updates
439
440    #def get_context_data(self, **kwargs):
441    #    context = super(GroupHistoryView, self).get_context_data(**kwargs)
442    #    if 'pk' in self.kwargs:
443    #        group = get_object_or_404(groups.models.Group, pk=self.kwargs['pk'])
444    #        context['title'] = "History for %s" % (group.name, )
445    #    else:
446    #        context['title'] = "Recent Changes"
447    #    return context
448
449
450@permission_required('groups.view_group_private_info')
451def group_confirmation_issues(request, ):
452    active_groups = groups.models.Group.active_groups
453    group_updates = forms.models.GroupMembershipUpdate.objects.all()
454    people_confirmations = forms.models.PersonMembershipUpdate.objects.filter(
455        deleted__isnull=True,
456        valid__gt=0,
457    )
458
459    buf = StringIO.StringIO()
460    output = csv.writer(buf)
461    output.writerow(['group_id', 'group_name', 'issue', 'num_confirm', 'officer_email', ])
462
463    q_present = Q(id__in=group_updates.values('group'))
464    missing_groups = active_groups.filter(~q_present)
465    #print len(list(group_updates))
466    for group in missing_groups:
467        num_confirms = len(people_confirmations.filter(groups=group))
468        output.writerow([
469            group.id,
470            group.name,
471            'unsubmitted',
472            num_confirms,
473            group.officer_email,
474        ])
475
476    for group_update in group_updates:
477        group = group_update.group
478        num_confirms = len(people_confirmations.filter(groups=group))
479        if num_confirms < 5:
480            output.writerow([
481                group.id,
482                group.name,
483                'confirmations',
484                num_confirms,
485                group.officer_email,
486            ])
487
488
489    return HttpResponse(buf.getvalue(), mimetype='text/plain', )
Note: See TracBrowser for help on using the repository browser.