diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py index a23027a516b685f6dd41e37add4a0da5258028db..6bbc463d1287bc56f83a29499f6dd8c1dd30d906 100644 --- a/mo/web/org_contest.py +++ b/mo/web/org_contest.py @@ -275,6 +275,9 @@ class ParticipantsFilterForm(PagerForm): contest_place = mo_fields.Place("Soutěžní oblast", render_kw={'autofocus': True}) participation_state = wtforms.SelectField('Stav účasti', choices=[('*', '*')] + list(db.PartState.choices()), default='*') + pant_email = wtforms.BooleanField("E-maily účastníků", default=True) + school_email = wtforms.BooleanField("E-maily jejich školních garantů", default=False) + # format = wtforms.RadioField(choices=[('', 'Zobrazit'), ('csv', 'Stáhnout vše v CSV'), ('tsv', 'Stáhnout vše v TSV')]) submit = wtforms.SubmitField("Zobrazit") download_csv = wtforms.SubmitField("↓ CSV") @@ -545,7 +548,7 @@ def org_import_org(round_id: Optional[int] = None, hier_id: Optional[int] = None contest=contest, round=round, default_place=default_place - ) + ) # URL je explicitně uvedeno v mo.email.contestant_list_url @@ -565,7 +568,8 @@ def org_generic_list(round_id: Optional[int] = None, hier_id: Optional[int] = No can_edit = rr.have_right(Right.manage_contest) and request.endpoint != 'org_generic_list_emails' format = request.args.get('format', "") - filter = ParticipantsFilterForm(formdata=request.args) + # XXX: Předáme-li prázdný slovník jako request.args, zresetují se booleovská políčka + filter = ParticipantsFilterForm(formdata=request.args if request.args else None) if request.args: filter.validate() @@ -587,13 +591,17 @@ def org_generic_list(round_id: Optional[int] = None, hier_id: Optional[int] = No if format == "": table = None emails = None + missing_org_warnings = None mailto_link = None if request.endpoint == 'org_generic_list_emails': if contest: subj = f'{contest.round.name} {contest.round.category} {contest.place.name_locative()}' else: subj = f'{round.name} kategorie {round.category}' - (emails, mailto_link) = get_contestant_emails(query, mailto_subject=subj) + (emails, mailto_link, missing_org_warnings) = \ + get_contestant_emails(query, mailto_subject=subj, + pant_email=filter.pant_email.data, + school_email=filter.school_email.data) count = len(emails) else: (count, query) = filter.apply_limits(query, pagesize=50) @@ -605,6 +613,7 @@ def org_generic_list(round_id: Optional[int] = None, hier_id: Optional[int] = No contest=contest, round=round, site=ctx.site, table=table, emails=emails, mailto_link=mailto_link, filter=filter, count=count, action_form=action_form, + missing_org_warnings=missing_org_warnings, ) else: table = make_contestant_table(query, round, add_school_orgs=True) @@ -733,15 +742,40 @@ def make_contestant_table(query: Query, round: db.Round, add_checkbox: bool = Fa ) -def get_contestant_emails(query: Query, mailto_subject: str = '[OSMO] Zpráva pro účastníky') -> Tuple[List[str], str]: - users = [pion.user for (pion, _, _) in query.all()] - emails = [f'{u.first_name} {u.last_name} <{u.email}>' for u in users] +def get_contestant_emails(query: Query, + mailto_subject: str, + pant_email: bool = True, + school_email: bool = True, + ) -> Tuple[List[str], str, List[str]]: + ctants = query.all() + + user_set: Set[db.User] + if pant_email: + user_set = set(pion.user for (pion, _, _) in ctants) + else: + user_set = set() + + org_warning_for: List[db.User] = [] + if school_email: + school_orgs = get_school_orgs(ctants) + for pion, pant, _ in ctants: + if school_orgs[pant.school]: + for u in school_orgs[pant.school]: + user_set.add(u) + else: + org_warning_for.append(pion.user) + + users = sorted(user_set, key=lambda u: u.sort_key()) + emails = [u.full_email() for u in users] + org_warnings = [u.full_name() for u in sorted(org_warning_for, key=lambda u: u.sort_key())] + mailto_link = ( - 'mailto:' + urllib.parse.quote(config.MAIL_CONTACT, safe='@') + 'mailto:' + urllib.parse.quote(g.user.full_email(), safe='@') + '?subject=' + urllib.parse.quote(mailto_subject) - + '&bcc=' + ','.join([urllib.parse.quote(email, safe='@') for email in emails]) + + '&bcc=' + ','.join([urllib.parse.quote(u.email, safe='@') for u in users]) ) - return (emails, mailto_link) + + return (emails, mailto_link, org_warnings) class SubmitForm(FlaskForm): diff --git a/mo/web/templates/org_generic_list.html b/mo/web/templates/org_generic_list.html index cddfcda9cbc408667feae0aee9b4b18d0841aad1..854df8042880b21271ce943a6ceae728afbec00d 100644 --- a/mo/web/templates/org_generic_list.html +++ b/mo/web/templates/org_generic_list.html @@ -27,6 +27,13 @@ {{ wtf.form_field(filter.school, size=8) }} {{ wtf.form_field(filter.participation_state) }} </div> + {% if not table %} + {{ wtf.form_field(filter.pant_email) }} + + {{ wtf.form_field(filter.school_email) }} + <div> + </div> + {% endif %} <div class="form-row" style="margin-top: 5px;"> <div class="btn-group"> {{ wtf.form_field(filter.submit, class='btn btn-primary') }} @@ -146,6 +153,11 @@ </p> {% endif %} {% else %} + {% if missing_org_warnings %} + <h3>Školní garant nenalezen pro tyto účastníky:</h3> + <pre>{{ missing_org_warnings|join('\n')|escape }}</pre> + {% endif %} + <h3>E-mailové adresy</h3> {% if emails %}