services.py 6.39 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
                'name': name,
                'periods': [period],
42
                'url': membership.group.get_absolute_url(),
43
44
                'earliest': membership.since,
            }
Thijs de Jong's avatar
Thijs de Jong committed
45
46
47
48
49
50
    return data


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

52
53
54
55
56
57
58
59
60
61
62
63
    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'])
64
65


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


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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()
97
        new['cohort'] = current_year - i
98
99
100
101
102
103
104
105
106
107
108
109
110
        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()
111
    new['cohort'] = gettext('Older')
112
113
114
115
116
117
118
119
120
121
122
123
    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
124
125
126
127
128


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

130
131
132
133
134
135
136
137
138
139
140
    :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
141

142
143
144
145
146
147
148
149
150
151
152
153
    :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
154

155
156
157
158
159
160
161
162
163
164
    :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)
165
166
167
168
169
170
171
172


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
Joren Vrancken's avatar
Joren Vrancken committed
173
    :return: list of processed members
174
175
    """
    members = (Member.objects
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
176
177
               .exclude(Q(membership__until__isnull=True) |
                        Q(membership__until__gt=timezone.now().date()))
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
               .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
193
            profile.address_country = None
194
195
196
197
198
199
200
201
202
            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