Coverage for website/mailinglists/services.py: 57.41%
40 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1"""The services defined by the mailinglists package."""
3from django.conf import settings
4from django.utils import timezone
6from activemembers.models import (
7 Board,
8 Committee,
9 MemberGroupMembership,
10 Mentorship,
11 Society,
12)
13from members.models import Member, Membership
14from utils.snippets import datetime_to_lectureyear
17def get_automatic_lists():
18 """Return list of mailing lists that should be generated automatically."""
19 current_committee_chairs = (
20 MemberGroupMembership.active_objects.filter(group__board=None)
21 .filter(group__society=None)
22 .filter(chair=True)
23 .select_related("member")
24 )
25 committee_chairs = _get_members_email_addresses(
26 [x.member for x in current_committee_chairs]
27 ) + ["internalaffairs@thalia.nu"]
29 current_society_chairs = (
30 MemberGroupMembership.active_objects.filter(group__board=None)
31 .filter(group__committee=None)
32 .filter(chair=True)
33 .select_related("member")
34 )
35 society_chair_emails = _get_members_email_addresses(
36 [x.member for x in current_society_chairs]
37 ) + ["internalaffairs@thalia.nu"]
39 active_committee_memberships = (
40 MemberGroupMembership.active_objects.filter(group__board=None)
41 .filter(group__society=None)
42 .select_related("member")
43 )
45 active_members = _get_members_email_addresses(
46 [x.member for x in active_committee_memberships]
47 )
49 lectureyear = datetime_to_lectureyear(timezone.now())
50 # Change to next lecture year after December
51 if 0 < timezone.now().month < 9: 51 ↛ 53line 51 didn't jump to line 53 because the condition on line 51 was always true
52 lectureyear += 1
53 active_mentorships = Mentorship.objects.filter(year=lectureyear).prefetch_related(
54 "member"
55 )
56 mentors = _get_members_email_addresses([x.member for x in active_mentorships])
58 oldmembers = [
59 m
60 for m in Member.objects.filter(profile__receive_oldmembers=True)
61 if (
62 m.current_membership is None
63 or m.current_membership.type != Membership.MEMBER
64 )
65 ]
67 lists = [
68 {
69 "name": "members",
70 "aliases": ["leden"],
71 "description": "Automatic moderated mailinglist that can be used "
72 "to send mail to all members",
73 "addresses": _get_members_email_addresses(
74 Member.all_with_membership(Membership.MEMBER)
75 ),
76 "moderated": True,
77 },
78 {
79 "name": "benefactors",
80 "aliases": ["begunstigers"],
81 "description": "Automatic moderated mailinglist that can be used "
82 "to send mail to all benefactors",
83 "addresses": _get_members_email_addresses(
84 Member.all_with_membership(Membership.BENEFACTOR)
85 ),
86 "moderated": True,
87 },
88 {
89 "name": "honorary",
90 "aliases": ["ereleden"],
91 "description": "Automatic moderated mailinglist that can be used "
92 "to send mail to all honorary members",
93 "addresses": _get_members_email_addresses(
94 Member.all_with_membership(Membership.HONORARY)
95 ),
96 "moderated": True,
97 },
98 {
99 "name": "oldmembers",
100 "description": "Automatic moderated mailinglist that can be used "
101 "to send mail to all former members, including honorary members. "
102 "Current members and benefactors are filtered out.",
103 "addresses": _get_members_email_addresses(oldmembers),
104 "moderated": True,
105 },
106 {
107 "name": "all",
108 "aliases": ["allen"],
109 "description": "Automatic moderated mailinglist that can be used "
110 "to send mail to all members, benefactors, honorary members",
111 "addresses": _get_members_email_addresses(
112 Member.all_with_membership(Membership.MEMBER)
113 + Member.all_with_membership(Membership.BENEFACTOR)
114 + Member.all_with_membership(Membership.HONORARY)
115 ),
116 "moderated": True,
117 },
118 {
119 "name": "mentors",
120 "description": "Automatic moderated mailinglist that can be used "
121 "to send mail to all orientation mentors. These "
122 "members should have a mentorship with the current "
123 "calendar year.",
124 "addresses": mentors,
125 "moderated": True,
126 },
127 {
128 "name": "activemembers",
129 "description": "Automatic moderated mailinglist that can be used "
130 "to send mail to all active members. These are all "
131 "users that are currently a member of a committee.",
132 "addresses": active_members,
133 "moderated": True,
134 },
135 {
136 "name": "committeechairs",
137 "aliases": ["commissievoorzitters"],
138 "description": "Automatic mailinglist that can be used to send "
139 "mail to all committee chairs",
140 "addresses": committee_chairs,
141 "moderated": False,
142 },
143 {
144 "name": "societychairs",
145 "aliases": ["gezelschapvoorzitters"],
146 "description": "Automatic mailinglist that can be used to send "
147 "mail to all society chairs",
148 "addresses": society_chair_emails,
149 "moderated": False,
150 },
151 {
152 "name": "optin",
153 "description": "Automatic mailinglist that can be used to send "
154 "mail to all members that have opted-in to receive "
155 "these (mostly recruitment) emails.",
156 "addresses": _get_members_email_addresses(
157 Member.current_members.filter(profile__receive_optin=True)
158 ),
159 "moderated": True,
160 },
161 {
162 "name": "committees",
163 "description": "Automatic moderated mailinglist that is a "
164 "collection of all committee lists",
165 "addresses": [
166 c.contact_address
167 for c in Committee.objects.all()
168 .filter(active=True)
169 .select_related("contact_mailinglist")
170 ],
171 "moderated": True,
172 },
173 {
174 "name": "societies",
175 "description": "Automatic moderated mailinglist that is a "
176 "collection of all society lists",
177 "addresses": [
178 c.contact_address
179 for c in Society.objects.all().select_related("contact_mailinglist")
180 ],
181 "moderated": True,
182 },
183 {
184 "name": "newsletter",
185 "description": "Automatic moderated mailinglist that can be used to send newsletters",
186 "addresses": _get_members_email_addresses(
187 Member.current_members.all().filter(profile__receive_newsletter=True)
188 ),
189 "moderated": True,
190 },
191 ]
193 all_previous_board_members = []
195 for board in Board.objects.filter(since__year__lte=lectureyear).order_by( 195 ↛ 198line 195 didn't jump to line 198 because the loop on line 195 never started
196 "since__year"
197 ):
198 board_members = [
199 board.member
200 for board in MemberGroupMembership.objects.filter(
201 group=board
202 ).prefetch_related("member")
203 ]
204 all_previous_board_members += board_members
205 years = str(board.since.year)[-2:] + str(board.until.year)[-2:]
206 lists.append(
207 {
208 "name": f"board{years}",
209 "aliases": [f"bestuur{years}"],
210 "description": "Automatic mailinglist to send email to all board "
211 f"members of {board.since.year}-{board.until.year}",
212 "addresses": _get_members_email_addresses(board_members),
213 "moderated": False,
214 }
215 )
217 lists.append(
218 {
219 "name": "oldboards",
220 "aliases": ["oudbesturen"],
221 "description": "Automatic mailinglist to send "
222 "email to all previous board members",
223 "moderated": True,
224 "addresses": _get_members_email_addresses(all_previous_board_members),
225 }
226 )
228 return lists
231def _get_members_email_addresses(members):
232 return_list = []
233 for member in members: 233 ↛ 234line 233 didn't jump to line 234 because the loop on line 233 never started
234 for email in get_member_email_addresses(member):
235 if email:
236 return_list.append(email)
237 return list(set(return_list))
240def get_member_email_addresses(member):
241 if member.is_staff and member.profile.email_gsuite_only:
242 return [
243 f"{member.username}@{settings.GSUITE_MEMBERS_DOMAIN}",
244 ]
245 if member.is_staff:
246 return [
247 member.email,
248 f"{member.username}@{settings.GSUITE_MEMBERS_DOMAIN}",
249 ]
250 return [member.email]