services.py 6.29 KB
Newer Older
1
from datetime import date
2

3
from django.db.models import Q
4
from django.utils import timezone
5
from django.utils.translation import gettext
6

7
from members import emails
8
from members.models import Membership, Member
9
10
from utils.snippets import datetime_to_lectureyear

11

Thijs de Jong's avatar
Thijs de Jong committed
12
def _member_group_memberships(member, skip_condition):
13
    memberships = member.membergroupmembership_set.all()
Thijs de Jong's avatar
Thijs de Jong committed
14
    data = {}
15

16
    for membership in memberships:
Thijs de Jong's avatar
Thijs de Jong committed
17
        if skip_condition(membership):
18
            continue
19
20
21
22
23
24
        period = {
            'since': membership.since,
            'until': membership.until,
            'chair': membership.chair
        }

25
        if hasattr(membership.group, 'board'):
26
27
28
            period['role'] = membership.role

        if (membership.until is None and
29
30
                hasattr(membership.group, 'board')):
            period['until'] = membership.group.board.until
31

32
        name = membership.group.name
Thijs de Jong's avatar
Thijs de Jong committed
33
34
35
36
37
        if data.get(name):
            data[name]['periods'].append(period)
            if data[name]['earliest'] > membership.since:
                data[name]['earliest'] = membership.since
            data[name]['periods'].sort(key=lambda x: x['since'])
38
        else:
Thijs de Jong's avatar
Thijs de Jong committed
39
            data[name] = {
40
41
42
43
                'name': name,
                'periods': [period],
                'earliest': membership.since,
            }
Thijs de Jong's avatar
Thijs de Jong committed
44
45
46
47
48
49
    return data


def member_achievements(member):
    achievements = _member_group_memberships(
        member, lambda membership: hasattr(membership.group, 'society'))
50

51
52
53
54
55
56
57
58
59
60
61
62
    mentor_years = member.mentorship_set.all()
    for mentor_year in mentor_years:
        name = "Mentor in {}".format(mentor_year.year)
        # Ensure mentorships appear last but are sorted
        earliest = date.today()
        earliest = earliest.replace(year=earliest.year + mentor_year.year)
        if not achievements.get(name):
            achievements[name] = {
                'name': name,
                'earliest': earliest,
            }
    return sorted(achievements.values(), key=lambda x: x['earliest'])
63
64


65
def member_societies(member):
Thijs de Jong's avatar
Thijs de Jong committed
66
67
68
    societies = _member_group_memberships(member, lambda membership: (
        hasattr(membership.group, 'board') or
        hasattr(membership.group, 'committee')))
69
70
71
    return sorted(societies.values(), key=lambda x: x['earliest'])


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def gen_stats_member_type(member_types):
    total = dict()
    for member_type in member_types:
        total[member_type] = (Membership
                              .objects
                              .filter(since__lte=date.today())
                              .filter(Q(until__isnull=True) |
                                      Q(until__gt=date.today()))
                              .filter(type=member_type)
                              .count())
    return total


def gen_stats_year(member_types):
    """
    Generate list with 6 entries, where each entry represents the total amount
    of Thalia members in a year. The sixth element contains all the multi-year
    students.
    """
    stats_year = []
    current_year = datetime_to_lectureyear(date.today())

    for i in range(5):
        new = dict()
96
        new['cohort'] = current_year - i
97
98
99
100
101
102
103
104
105
106
107
108
109
        for member_type in member_types:
            new[member_type] = (
                Membership.objects
                .filter(user__profile__starting_year=current_year - i)
                .filter(since__lte=date.today())
                .filter(Q(until__isnull=True) |
                        Q(until__gt=date.today()))
                .filter(type=member_type)
                .count())
        stats_year.append(new)

    # Add multi year members
    new = dict()
110
    new['cohort'] = gettext('Older')
111
112
113
114
115
116
117
118
119
120
121
122
    for member_type in member_types:
        new[member_type] = (
            Membership.objects
            .filter(user__profile__starting_year__lt=current_year - 4)
            .filter(since__lte=date.today())
            .filter(Q(until__isnull=True) |
                    Q(until__gt=date.today()))
            .filter(type=member_type)
            .count())
    stats_year.append(new)

    return stats_year
123
124
125
126
127


def verify_email_change(change_request):
    """
    Mark the email change request as verified
128

129
130
131
132
133
134
135
136
137
138
139
    :param change_request: the email change request
    """
    change_request.verified = True
    change_request.save()

    process_email_change(change_request)


def confirm_email_change(change_request):
    """
    Mark the email change request as verified
140

141
142
143
144
145
146
147
148
149
150
151
152
    :param change_request: the email change request
    """
    change_request.confirmed = True
    change_request.save()

    process_email_change(change_request)


def process_email_change(change_request):
    """
    Change the user's email address if the request was completed and
    send the completion email
153

154
155
156
157
158
159
160
161
162
163
    :param change_request: the email change request
    """
    if not change_request.completed:
        return

    member = change_request.member
    member.email = change_request.email
    member.save()

    emails.send_email_change_completion_message(change_request)
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200


def execute_data_minimisation(dry_run=False):
    """
    Clean the profiles of members/users of whom the last membership ended
    at least 31 days ago

    :param dry_run: does not really remove data if True
    :return list of processed members
    """
    members = (Member.objects
               .filter(Q(membership__until__isnull=False) |
                       Q(membership__until__lte=timezone.now().date()))
               .distinct()
               .prefetch_related('membership_set', 'profile'))
    deletion_period = timezone.now().date() - timezone.timedelta(days=31)
    processed_members = []
    for member in members:
        if (member.latest_membership is None or
                member.latest_membership.until <= deletion_period):
            processed_members.append(member)
            profile = member.profile
            profile.student_number = None
            profile.phone_number = None
            profile.address_street = None
            profile.address_street2 = None
            profile.address_postal_code = None
            profile.address_city = None
            profile.birthday = None
            profile.emergency_contact_phone_number = None
            profile.emergency_contact = None
            profile.website = None
            profile.bank_account = None
            if not dry_run:
                profile.save()

    return processed_members