source: asadb/space/diffs.py @ d85ba8f

space-accessstablestage
Last change on this file since d85ba8f was bec7760, checked in by Alex Dehnert <adehnert@…>, 14 years ago

office access: initial diff script

  • Property mode set to 100755
File size: 6.3 KB
RevLine 
[bec7760]1#!/usr/bin/python
2import collections
3import datetime
4import os
5import sys
6
7if __name__ == '__main__':
8    cur_file = os.path.abspath(__file__)
9    django_dir = os.path.abspath(os.path.join(os.path.dirname(cur_file), '..'))
10    sys.path.append(django_dir)
11    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
12
13from django.core.mail import EmailMessage
14from django.db import connection
15from django.db.models import Q
16from django.template import Context, Template
17from django.template.loader import get_template
18
19import groups.diffs
20import groups.models
21import space.models
22import util.emails
23
24role = {}
25people_name = {} # username -> full name
26people_id = {} # username -> MIT ID
27
28all_spaces = {} # Space.pk -> Space
29
30def fill_people(holder):
31    if not holder.person in people_name:
32        try:
33            person = groups.models.AthenaMoiraAccount.objects.get(username=holder.person)
34            people_name[holder.person] = person.format()
35            people_id[holder.person] = person.mit_id
36        except groups.models.AthenaMoiraAccount.DoesNotExist:
37            people_name[holder.person] = "<%s>" % (holder.person, )
38            people_id[holder.person] = None
39
40class GroupInfo(object):
41    def __init__(self, group, ):
42        self.group = group
43        self.offices = {}  # Space.pk -> (ID -> (Set name, Set name))
44        if not role:
45            role['office'] = groups.models.OfficerRole.objects.get(slug='office-access')
46
47    def learn_access(self, space_pk, old, new):
48        group_pk = self.group.pk
49        if group_pk in old:
50            old_access = old[group_pk]
51        else: old_access = {}
52        if group_pk in new:
53            new_access = new[group_pk]
54        else: new_access = {}
55        assert space_pk not in self.offices
56
57        # Let's fill out the self.offices set.
58        self.offices[space_pk] = collections.defaultdict(lambda: (set(), set()))
59        space_data = self.offices[space_pk]
60        for mit_id, old_set in old_access.items():
61            space_data[mit_id][0].extend(old_set)
62        for mit_id, new_set in new_access.items():
63            space_data[mit_id][1].extend(new_set_set)
64
65    def add_space_signatories(self, old_time, new_time, ):
66        group = self.group
67        old_people = group.officers(as_of=old_time, role=role['office'])
68        new_people = group.officers(as_of=new_time, role=role['office'])
69        for holder in old_people:
70            fill_people(holder)
71        for holder in new_people:
72            fill_people(holder)
73        for office_id, office_data in self.offices.items():
74            for holder in old_people:
75                holder_name = people_name[holder.person]
76                holder_id = people_id[holder.person]
77                office_data[holder_id][0].add(holder_name)
78            for holder in new_people:
79                holder_name = people_name[holder.person]
80                holder_id = people_id[holder.person]
81                office_data[holder_id][1].add(holder_name)
82
83    def list_changes(self, ):
84        cac_lines = []
85        group_lines = []
86        def append_change(mit_id, verb, name):
87            cac_lines.append("%s:\t%s:\t%s" % (mit_id, verb, name))
88            group_lines.append("%s:\t%s" % (verb, name))
89        changes = False
90        for space_pk, space_data in self.offices.items():
91            line = "Changes in %s:" % (all_spaces[space_pk].number, )
92            cac_lines.append(line)
93            group_lines.append(line)
94            for mit_id, (old_names, new_names) in space_data.items():
95                if mit_id is None: mit_id = "ID unknown"
96                if old_names == new_names:
97                    pass
98                else:
99                    changes = True
100                    for name in old_names:
101                        if name in new_names:
102                            append_change(mit_id, "Keep", name)
103                        else:
104                            append_change(mit_id, "Remove", name)
105                    for name in new_names:
106                        if name in old_names:
107                            pass
108                        else:
109                            append_change(mit_id, "Add", name)
110            cac_lines.append("")
111            group_lines.append("")
112
113        cac_msg = "\n".join(cac_lines)
114        group_msg = "\n".join(group_lines)
115        return changes, cac_msg, group_msg
116
117def init_groups(the_groups, assignments):
118    for assignment in assignments:
119        group = assignment.group
120        if group.id not in the_groups:
121            the_groups[group.id] = GroupInfo(group)
122
123def space_specific_access(group_data, old_time, new_time, ):
124    process_spaces =  space.models.Space.objects.all()
125    #process_spaces = process_spaces.filter(number="W20-467")
126    for the_space in process_spaces:
127        old_data = the_space.build_access(time=old_time)
128        new_data = the_space.build_access(time=new_time)
129        all_spaces[the_space.pk] = the_space
130        init_groups(group_data, old_data[1])
131        init_groups(group_data, new_data[1])
132        for group_pk, group in group_data.items():
133            if group_pk in old_data[0] or group_pk in new_data[0]:
134                group.learn_access(the_space.pk, old_data[0], new_data[0])
135
136
137def space_access_diffs():
138    new_time = datetime.datetime.utcnow()
139    old_time = new_time - datetime.timedelta(days=1)
140    group_data = {} # Group.pk -> GroupInfo
141    changed_groups = []
142    space_specific_access(group_data, old_time, new_time)
143    for group_pk, group_info in group_data.items():
144        group_info.add_space_signatories(old_time, new_time)
145        changes, cac_changes, group_changes = group_info.list_changes()
146        if changes:
147            changed_groups.append((group_info.group, cac_changes, group_changes))
148
149    asa_rcpts = ['asa-space@mit.edu', 'asa-db@mit.edu', ]
150    util.emails.email_from_template(
151        tmpl='space/cac-change-email.txt',
152        context={'changed_groups': changed_groups},
153        subject="Office access updates",
154        to=['caclocks@mit.edu'],
155        cc=asa_rcpts,
156    ).send()
157    for group, cac_msg, group_msg in changed_groups:
158        util.emails.email_from_template(
159            tmpl='space/group-change-email.txt',
160            context={
161                'group':group,
162                'msg':group_msg,
163            },
164            subject="Office access updates",
165            to=[group.officer_email],
166            cc=asa_rcpts,
167        ).send()
168       
169
170if __name__ == "__main__":
171    space_access_diffs()
Note: See TracBrowser for help on using the repository browser.