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

1"""The services defined by the mailinglists package.""" 

2 

3from django.conf import settings 

4from django.utils import timezone 

5 

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 

15 

16 

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"] 

28 

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"] 

38 

39 active_committee_memberships = ( 

40 MemberGroupMembership.active_objects.filter(group__board=None) 

41 .filter(group__society=None) 

42 .select_related("member") 

43 ) 

44 

45 active_members = _get_members_email_addresses( 

46 [x.member for x in active_committee_memberships] 

47 ) 

48 

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]) 

57 

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 ] 

66 

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 ] 

192 

193 all_previous_board_members = [] 

194 

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 ) 

216 

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 ) 

227 

228 return lists 

229 

230 

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)) 

238 

239 

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]