Changeset 251503b


Ignore:
Timestamp:
Nov 4, 2012, 2:48:18 AM (13 years ago)
Author:
Alex Dehnert <adehnert@…>
Branches:
master, space-access, stable, stage
Children:
0a31846
Parents:
c547de5 (diff), bda4d86 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Alex Dehnert <adehnert@…> (11/04/12 02:48:18)
git-committer:
Alex Dehnert <adehnert@…> (11/04/12 02:48:18)
Message:

Merge branch 'membership-confirm'

Location:
asadb
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • asadb/forms/admin.py

    r0229bd5 rbda4d86  
    3838        'pk',
    3939        'group',
     40        'cycle',
    4041        'update_time',
    4142        'updater_name',
     
    4748        'num_other',
    4849    )
     50    list_filter = ('cycle', )
    4951    list_display_links = ('pk', 'group', )
    5052    search_fields = ('group__name', 'group__abbreviation', 'updater_name', )
  • asadb/forms/models.py

    r8eca9da rbda4d86  
    155155    updater_title = models.CharField(max_length=30, help_text="You need not hold any particular title in the group, but we like to know who is completing the form.")
    156156   
     157    cycle = models.ForeignKey(GroupConfirmationCycle)
    157158    group = models.ForeignKey(groups.models.Group, help_text="If your group does not appear in the list above, then please email asa-exec@mit.edu.", db_index=True, )
    158159    group_email = models.EmailField(help_text="The text of the law will be automatically distributed to your members via this list, in order to comply with the law.")
  • asadb/forms/views.py

    rcbdbd1f rbda4d86  
    66
    77from django.contrib.auth.decorators import user_passes_test, login_required, permission_required
     8from django.core.exceptions import PermissionDenied
    89from django.views.generic import list_detail, ListView, DetailView
    910from django.shortcuts import render_to_response, get_object_or_404
     
    4041            self.fields["group"].queryset = queryset
    4142
    42 def select_group(request, url_name_after, pagename='homepage', queryset=None, ):
     43def select_group(request, url_name_after, url_args=[], pagename='homepage', queryset=None, title="", msg=""):
    4344    if request.method == 'POST': # If the form has been submitted...
    4445        # A form bound to the POST data
     
    4647        if form.is_valid(): # All validation rules pass
    4748            group = form.cleaned_data['group'].id
    48             return HttpResponseRedirect(reverse(url_name_after, args=[group],)) # Redirect after POST
     49            return HttpResponseRedirect(reverse(url_name_after, args=url_args+[group],)) # Redirect after POST
    4950    else:
    5051        form = SelectGroupForm(queryset=queryset, ) # An unbound form
    5152
     53    if not title: title = "Select group"
    5254    context = {
    5355        'form':form,
     56        'title':title,
     57        'msg':msg,
    5458        'pagename':pagename,
    5559    }
     
    171175    try:
    172176        fysm_obj = forms.models.FYSM.objects.get(group=group_obj, year=year, )
    173         print "Successfully found", fysm_obj.__dict__
    174177    except forms.models.FYSM.DoesNotExist:
    175178        fysm_obj = forms.models.FYSM()
     
    244247membership_update_qs = groups.models.Group.objects.filter(group_status__slug__in=['active', 'suspended', ])
    245248
     249@login_required
     250def group_membership_update_select_group(request, ):
     251    cycle = forms.models.GroupConfirmationCycle.latest()
     252
     253    users_groups = groups.models.Group.involved_groups(request.user.username)
     254    qs = membership_update_qs.filter(pk__in=users_groups)
     255
     256    return select_group(request=request,
     257        url_name_after='membership-update-group',
     258        url_args=[cycle.slug],
     259        pagename='groups',
     260        queryset=qs,
     261        title="Submit membership update for...",
     262        msg="The list below contains only groups that list you as being involved. You must be an administrator of a group to submit an update.",
     263    )
     264
    246265class Form_GroupMembershipUpdate(ModelForm):
    247     group = ModelChoiceField(queryset=membership_update_qs)
    248 
    249266    def __init__(self, *args, **kwargs):
    250267        super(Form_GroupMembershipUpdate, self).__init__(*args, **kwargs)
     
    254271        model = forms.models.GroupMembershipUpdate
    255272        fields = [
    256             'group',
    257273            'updater_title',
    258274            'group_email',
     
    271287
    272288@login_required
    273 def group_membership_update(request, ):
    274     year = datetime.date.today().year
    275 
    276     initial = {
    277     }
    278     update_obj = forms.models.GroupMembershipUpdate()
    279     update_obj.update_time  = datetime.datetime.now()
    280     update_obj.updater_name = request.user.username
     289def group_membership_update(request, cycle_slug, pk, ):
     290    cycle = get_object_or_404(forms.models.GroupConfirmationCycle, slug=cycle_slug)
     291    group_obj = get_object_or_404(groups.models.Group, pk=pk)
     292    if not request.user.has_perm('groups.admin_group', group_obj):
     293        raise PermissionDenied
     294
     295    try:
     296        update_obj = forms.models.GroupMembershipUpdate.objects.get(group=group_obj, cycle=cycle, )
     297    except forms.models.GroupMembershipUpdate.DoesNotExist:
     298        update_obj = None
    281299
    282300    confirm_path = reverse('membership-confirm', )
     
    284302         request.get_host(), confirm_path)
    285303
    286     if request.method == 'POST': # If the form has been submitted...
     304    if request.method == 'POST':
    287305        form = Form_GroupMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data
    288306
    289307        if form.is_valid(): # All validation rules pass
     308            # Update the updater info
     309            form.instance.group = group_obj
     310            form.instance.cycle = cycle
     311            form.instance.update_time  = datetime.datetime.now()
     312            form.instance.updater_name = request.user.username
    290313            request_obj = form.save()
    291             group_obj = request_obj.group
    292 
    293314
    294315            # Send email
     
    335356
    336357    else:
    337         form = Form_GroupMembershipUpdate(initial=initial, ) # An unbound form
     358        form = Form_GroupMembershipUpdate(instance=update_obj)
    338359
    339360    context = {
    340361        'form':form,
     362        'group':group_obj,
    341363        'confirm_uri': confirm_uri,
    342364        'pagename':'groups',
     
    354376@login_required
    355377def person_membership_update(request, ):
    356     year = datetime.date.today().year
    357 
    358378    initial = {
    359379    }
    360380    cycle = forms.models.GroupConfirmationCycle.latest()
     381
     382    # Initialize/find the PersonMembershipUpdate for this user
    361383    try:
    362384        update_obj = forms.models.PersonMembershipUpdate.objects.get(
     
    366388        )
    367389        selected_groups = update_obj.groups.all()
    368         print "Got update"
    369390    except forms.models.PersonMembershipUpdate.DoesNotExist:
    370391        update_obj = forms.models.PersonMembershipUpdate()
     
    374395        selected_groups = []
    375396
     397    # Determine whether the submitter is a student or not
    376398    accounts = groups.models.AthenaMoiraAccount
    377399    try:
     
    387409    update_obj.save()
    388410
     411    # Find groups that list a role for the user
     412    office_holders = groups.models.OfficeHolder.current_holders.filter(person=request.user.username)
     413    role_groups = {}
     414    for office_holder in office_holders:
     415        if office_holder.group.pk not in role_groups:
     416            role_groups[office_holder.group.pk] = (office_holder.group, set())
     417        role_groups[office_holder.group.pk][1].add(office_holder.role.display_name)
     418
     419    # Find groups the user searched for
    389420    filterset = groups.views.GroupFilter(request.GET, membership_update_qs)
    390421    filtered_groups = filterset.qs.all()
     
    394425    message_type = "info"
    395426
     427    if update_obj.valid <= forms.models.VALID_UNSET:
     428        message = "You are not listed as a student. While you're welcome to confirm your membership in groups anyway, you will not count towards the five student member requirement. If you are a student, please contact asa-exec so that we can correct our records."
     429        message_type = "warn"
     430
     431    # Handle the single group add/remove forms
     432    # * removing previously confirmed groups
     433    # * add/remove groups that list the user in a role
     434    # * add/remove groups the user searched for
    396435    if request.method == 'POST' and 'add-remove' in request.POST:
    397436        group = groups.models.Group.objects.get(id=request.POST['group'])
     
    399438            if group in update_obj.groups.all():
    400439                update_obj.groups.remove(group)
    401                 message = "You have been successfully removed from %s." % (group, )
     440                message = "You have successfully unconfirmed membership in %s." % (group, )
    402441            else:
    403                 message = "Sorry, but you're not in %s." % (group, )
     442                message = "Removal failed because you had not confirmed membership in %s." % (group, )
    404443                message_type = "warn"
    405444        elif request.POST['action'] == 'add':
    406445            if group in update_obj.groups.all():
    407                 message = "Sorry, but you're already in %s." % (group, )
     446                message = "Membership in %s already confirmed." % (group, )
    408447                message_type = "warn"
    409448            else:
    410449                update_obj.groups.add(group)
    411                 message = "You have been successfully added to %s." % (group, )
     450                message = "You have successfully confirmed membership in %s." % (group, )
    412451        else:
    413452            message = "Uh, somehow you tried to do something besides adding and removing..."
    414453            message_type = "alert"
    415454
    416     if request.method == 'POST' and 'list' in request.POST: # If the form has been submitted...
    417         form = Form_PersonMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data
    418 
    419         if form.is_valid(): # All validation rules pass
     455    # Handle the big list of groups
     456    if request.method == 'POST' and 'list' in request.POST:
     457        form = Form_PersonMembershipUpdate(request.POST, request.FILES, instance=update_obj)
     458        if form.is_valid():
    420459            request_obj = form.save()
    421460            message = "Update saved"
    422 
    423461    else:
    424         form = Form_PersonMembershipUpdate(initial=initial, instance=update_obj, ) # An unbound form
    425 
     462        form = Form_PersonMembershipUpdate(initial=initial, instance=update_obj, )
     463
     464    # Render the page
    426465    context = {
     466        'role_groups':role_groups,
    427467        'form':form,
    428468        'filter':filterset,
     
    442482
    443483    def get_queryset(self):
     484        cycle = forms.models.GroupConfirmationCycle.latest()
    444485        group_updates = forms.models.GroupMembershipUpdate.objects.all()
    445486        group_updates = group_updates.filter(
     487            cycle=cycle,
     488            group__personmembershipupdate__cycle=cycle,
    446489            group__personmembershipupdate__deleted__isnull=True,
    447490            group__personmembershipupdate__valid__gt=0,
     
    482525        group = group_update.group
    483526        num_confirms = len(people_confirmations.filter(groups=group))
     527        problems = []
     528
    484529        if num_confirms < 5:
     530            problems.append("confirmations")
     531
     532        num_students = group_update.num_undergrads + group_update.num_grads
     533        num_other = group_update.num_alum + group_update.num_other_affiliate + group_update.num_other
     534        if num_students < num_other:
     535            problems.append("50%")
     536
     537        for problem in problems:
    485538            output.writerow([
    486539                group.id,
    487540                group.name,
    488                 'confirmations',
     541                problem,
    489542                num_confirms,
    490543                group.officer_email,
     
    492545
    493546
    494     return HttpResponse(buf.getvalue(), mimetype='text/plain', )
     547    return HttpResponse(buf.getvalue(), mimetype='text/csv', )
  • asadb/groups/models.py

    r54babcd rbda4d86  
    105105    def __str__(self, ):
    106106        return self.name
     107
     108    @staticmethod
     109    def involved_groups(username):
     110        current_officers = OfficeHolder.current_holders.filter(person=username)
     111        users_groups = Group.objects.filter(officeholder__in=current_officers).distinct()
     112        return users_groups
    107113
    108114    @classmethod
  • asadb/template/forms/select.html

    rc9d8369 rbda4d86  
    44{% block content %}
    55
    6 <h2>Select Group</h2>
     6<h2>{{title}}</h2>
     7
     8{% if msg %}<p>{{msg}}</p>{%endif%}
    79
    810<form method="post" action="">
  • asadb/template/index.html

    rab17953 rbda4d86  
    4343        <li><a href='{%url fysm-select%}'>Submit an entry</a></li>
    4444    </ul></li>
    45     {% comment %}
    4645    <li>Membership updates<ul>
    47         <li><a href='{%url membership-update%}'>Group update</a></li>
     46        <li><a href='{%url membership-update-cycle %}'>Group update</a></li>
    4847        <li><a href='{%url membership-confirm%}'>Individual confirmations</a></li>
    4948        <li><a href='{%url membership-submitted%}'>Groups with submitted updates</a></li>
    5049        {% if perms.groups.view_group_private_info %}<li><a href='{%url membership-issues%}'>Issues</a> (CSV)</li>{% endif %}
    5150    </ul></li>
    52     {% endcomment %}
    5351    <li>Group recognition<ul>
    5452        <li><a href='http://web.mit.edu/asa/start/new-group-app.html'>New Group Application</a></li>
  • asadb/template/membership/confirm.html

    r56e8cb8 r11941e1  
    1414<p>
    1515The ASA is attempting to verify that all currently recognized groups are active
    16 and have at least five members.
     16and have at least five student members.
    1717</p>
    1818
     
    2121<h3>Groups you currently say you're a member of:</h3>
    2222{% if member_groups %}
    23 <ul>
     23<table class='pretty-table'>
     24<thead>
     25<tr>
     26    <th>Group</th>
     27    <th></th>
     28</tr>
     29</thead>
     30<tbody>
    2431{% for group in member_groups %}
    25     <li>{{group}}</li>
     32<tr>
     33    <th>{{group}}</th>
     34    <td><form action="" method="post">
     35        <input type="hidden" name="group" value="{{group.pk}}">
     36        {% csrf_token %}
     37        <input type="hidden" name="action" value="remove">
     38        <input type="submit" name="add-remove" value="Remove">
     39    </form></td>
     40</tr>
    2641{% endfor %}
    27 </ul>
     42</tbody>
     43</table>
    2844{% else %}
    2945<p>You are not currently indicating membership in any groups.</p>
    3046{% endif %}
    3147
    32 <h3>Option 1: Add or remove groups one at a time</h3>
     48<h3>Option 1: Add or remove groups that list a role for you</h3>
     49
     50<table class='pretty-table'>
     51<thead>
     52<tr>
     53    <th>Group</th>
     54    <th>Roles</th>
     55    <th>Add/Remove</th>
     56</tr>
     57</thead>
     58<tbody>
     59{% for group, roles in role_groups.values %}
     60<tr>
     61    <th>{{group}}</th>
     62    <td>{{roles|join:", "}}</td>
     63    <td><form action="" method="post">
     64        <input type="hidden" name="group" value="{{group.pk}}">
     65        {% csrf_token %}
     66        {% if group in member_groups %}
     67        <input type="hidden" name="action" value="remove">
     68        <input type="submit" name="add-remove" value="Remove">
     69        {% else %}
     70        <input type="hidden" name="action" value="add">
     71        <input type="submit" name="add-remove" value="Add">
     72        {% endif %}
     73    </form></td>
     74</tr>
     75{% endfor %}
     76</tbody>
     77</table>
     78
     79<h3>Option 2: Add or remove groups by searching</h3>
    3380
    3481<form action="" method="get">
     
    80127
    81128
    82 <h3>Option 2: Select all your groups at once</h3>
     129<h3>Option 3: Select all your groups at once</h3>
    83130
    84131<p>Below is a list of all recognized groups. You can go through picking out the groups you are a member of. However, you should be careful not to deselect any groups (unless you aren't a member of them, of course).</p>
  • asadb/template/membership/update.html

    rf48884a rbda4d86  
    5757{% csrf_token %}
    5858<table class='pretty-table'>
     59<tr>
     60    <th>Group</th>
     61    <td>{{group}}</td>
     62</tr>
    5963{{ form.as_table }}
    6064<tr><th colspan='2'><input type='submit' value='Submit membership update' /></th></tr>
  • asadb/urls.py

    r2c86ed1 rbda4d86  
    4646    url(r'^fysm/(?:(\d+)/)?(?:([\w-]+)/)?$', forms.views.fysm_by_years, name='fysm', ),
    4747
    48     url(r'^membership/update/$', forms.views.group_membership_update, name='membership-update', ),
     48    url(
     49        regex=r'^membership/update/$',
     50        view=forms.views.group_membership_update_select_group,
     51        name='membership-update-cycle',
     52    ),
     53    url(r'^membership/update/(?P<cycle_slug>[\w-]+)/(?P<pk>\d+)/$', forms.views.group_membership_update, name='membership-update-group', ),
    4954    url(r'^membership/confirm/$', forms.views.person_membership_update, name='membership-confirm', ),
    5055    url(
  • asadb/groups/diffs.py

    rac9b167 r9882429  
    2727if settings.PRODUCTION_DEPLOYMENT:
    2828    asa_all_groups_list = util.mailinglist.MailmanList('asa-official')
     29    gsc_fb_list = util.mailinglist.MailmanList('gsc-fb-')
    2930    finboard_groups_list = util.mailinglist.MoiraList('finboard-groups-only')
    3031else:
    3132    asa_all_groups_list = util.mailinglist.MailmanList('asa-test-mailman')
     33    gsc_fb_list = util.mailinglist.MailmanList('asa-test-mailman')
    3234    finboard_groups_list = util.mailinglist.MoiraList('asa-test-moira')
    3335
     
    246248    fundings = groups.models.GroupFunding.objects
    247249    fund_pk = fundings.get(slug=funding_slug).pk
    248     print "funded_pred: %s %s" % (class_pk, fund_pk)
    249250    def pred(version, fields):
    250251        return fields['group_class'] == class_pk and fields['group_funding'] == fund_pk
     
    295296        include_pred=funded_pred('undergrad'),
    296297    ))
     298    callbacks.append(UpdateOfficerListCallback(
     299        listobj=gsc_fb_list,
     300        include_pred=funded_pred('grad'),
     301    ))
    297302    return callbacks
    298303
  • asadb/groups/format_groups.py

    ra7d30ef rc547de5  
    22
    33import csv
     4import datetime
    45import os
    56import sys
     
    4546    'midway' : {
    4647        'prefix': """
    47         <!-- Automatically generated by %(script)s %(mode)s.
    48         Do not edit; instead re-run that script (or edit it as necessary). -->
     48        <!--
     49        Automatically generated by %(script)s %(mode)s on %(date)s.
     50        Do not edit; instead ask a DB maintainer (asa-db@) to re-run that script (or edit script as necessary).
     51
     52        A more recent version may be in /mit/asa-db/data/db-dump/midway_groups.html.
     53        Includes active, suspended, applying, and NGE's (status) who aren't Dorm/FSILG (class).
     54        -->
    4955        """,
    5056        'format' : '<option value="%(html_name)s">%(html_name)s</option>',
     
    7480    predicate = spec['predicate']
    7581    gs = groups.models.Group.objects.filter(predicate).distinct()
    76     static_args = {'script': 'groups/format_groups.py', 'mode':mode, }
     82    static_args = {
     83        'script': 'groups/format_groups.py',
     84        'mode':mode,
     85        'date':datetime.datetime.now(),
     86    }
    7787    if 'prefix' in spec:
    7888        print spec['prefix'] % static_args
  • asadb/groups/migrations/0019_initial_revs.py

    ra1ff79a r6f0e814  
    1515            'password':'SYSTEM',
    1616        })
    17         call_command('createinitialrevisions', 'groups', )
     17        reversion_models = ['Group', 'GroupStartup', 'GroupNote', 'OfficerRole', 'OfficeHolder', ]
     18        reversion_model_specs = [ 'groups.%s' % (model, ) for model in reversion_models ]
     19        call_command('createinitialrevisions', *reversion_model_specs)
    1820
    1921
  • asadb/groups/views.py

    r4bf8692 re034df6  
    621621        self.fields['constitution_url'].required = True
    622622        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."
     623        self.fields['athena_locker'].required = True
    623624
    624625    class Meta(GroupCreateForm.Meta):
  • asadb/space/admin.py

    rcbffe98 r465eb7a  
    1919        'group',
    2020        'space',
     21        'locker_num',
    2122        'start',
    2223        'end',
  • asadb/space/migrations/0004_add_ebm_permissions.py

    r3d75d13 r5f1eaa3  
    3737    def forwards(self, orm):
    3838        "Write your forwards methods here."
     39
     40        # See https://groups.google.com/forum/?fromgroups=#!topic/south-users/ZmmUyrrRoYU or groups:0006_add_group_perms
     41        db.send_pending_create_signals()
     42
    3943        self.modify_perms(orm, lambda perms, perm: perms.add(perm))
    4044
  • asadb/space/models.py

    ra03cb61 r7eea15c  
    145145
    146146    name = models.CharField(max_length=50)
    147     card_number = models.CharField(max_length=20)
     147    card_number = models.CharField(max_length=20, verbose_name="MIT ID", help_text="MIT ID number (as printed on, eg, the relevant ID card)")
    148148
    149149    objects = models.Manager()
  • asadb/template/groups/diffs/new-group-announce.txt

    rd768e47 r264efa0  
    55to the MIT community!
    66
    7 The last step to finalize the group recognition is for you to enter the
     7The last step to finalize the group recognition is for you to finish entering the
    88group's complete information into the ASA Database:
    99
    1010      http://web.mit.edu/asa/www/asa-db.shtml
     11
     12Your group's entry is at:
     13
     14      http://asa.mit.edu/{% url groups:group-detail group.pk %}
     15
     16You should make sure to do the following:
     17* add membership numbers
     18* put your constitution somewhere permanent (preferably in your group's Athena
     19  locker, {{group.athena_locker}}) and list the new location in the DB
     20
     21You may also want to:
     22* add your website and meeting times so potential members can find
     23  you more easily
     24* add any group officers who should be able to reserve rooms, update your DB
     25  entry, etc.
    1126
    1227Note that at this point only the President and Treasurer of the group
  • asadb/util/export_website_groups.py

    r884ab7c rc547de5  
    55
    66import codecs
     7import datetime
    78import os
    89import sys
     
    1819
    1920TMPL = Template(u"""
    20 <!-- Automatically generated by asadb/util/export_website_groups.py.
    21 Do not edit; instead re-run that script (or edit it as necessary). -->
     21<!--
     22Automatically generated by asadb/util/export_website_groups.py on {{date}}.
     23Do not edit; instead ask a DB maintainer (asa-db@) to re-run that script (or edit script as necessary).
     24
     25A more recent version may be in /mit/asa-db/data/db-dump/website_groups.html.
     26Includes groups with status is_active=True (ie, Suspended and Active groups).
     27-->
    2228{% for group in groups %}
    2329<tr><td>
     
    3238
    3339if __name__ == '__main__':
    34     ctx = Context(
    35         {'groups': groups.models.Group.objects.filter(group_status__is_active=True)}
    36     )
    37     out = codecs.getwriter('utf8')(sys.stdout)
     40    ctx = Context({
     41        'groups': groups.models.Group.objects.filter(group_status__is_active=True),
     42        'date': datetime.datetime.now(),
     43    })
     44    out = codecs.getwriter('utf-8')(sys.stdout)
    3845    out.write(TMPL.render(ctx))
Note: See TracChangeset for help on using the changeset viewer.