diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py
index 6bbc463d1287bc56f83a29499f6dd8c1dd30d906..552a569e0d0166feee1183de3b9367fe1fec764a 100644
--- a/mo/web/org_contest.py
+++ b/mo/web/org_contest.py
@@ -8,7 +8,7 @@ import json
import locale
import magic
from markupsafe import Markup
-from sqlalchemy import func, and_, select, not_
+from sqlalchemy import func, and_, not_
from sqlalchemy.orm import joinedload, aliased
from sqlalchemy.orm.query import Query
from sqlalchemy.dialects.postgresql import insert as pgsql_insert
@@ -28,6 +28,7 @@ import mo.jobs.protocols
import mo.jobs.submit
from mo.rights import Right, RoundRights
import mo.util
+from mo.util import assert_not_none
from mo.util_format import inflect_number, inflect_by_number, inflect_with_number
from mo.web import app
import mo.web.fields as mo_fields
@@ -1533,12 +1534,12 @@ def org_contest_advance(ct_id: int):
reject_by_place_id: Dict[int, int] = {}
prev_pions_by_place_id: Dict[int, List[Tuple[db.Participation, Optional[decimal.Decimal], bool]]] = {}
- desc_cte = db.place_descendant_cte(contest.place, max_level=prev_round.level)
- prev_contests = (sess.query(db.Contest)
- .filter(db.Contest.round == prev_round)
- .filter(db.Contest.place_id.in_(select([desc_cte])))
- .options(joinedload(db.Contest.place))
- .all())
+ prev_contests_q = sess.query(db.Contest).filter(db.Contest.round == prev_round)
+ if prev_round.level >= round.level:
+ prev_contests_q = prev_contests_q.join(db.RegionDescendant, and_(db.RegionDescendant.region == contest.place_id, db.RegionDescendant.descendant == db.Contest.place_id))
+ else:
+ prev_contests_q = prev_contests_q.join(db.RegionDescendant, and_(db.RegionDescendant.descendant == contest.place_id, db.RegionDescendant.region == db.Contest.place_id))
+ prev_contests = prev_contests_q.options(joinedload(db.Contest.place)).all()
prev_contests.sort(key=lambda c: locale.strxfrm(c.place.name or ""))
form = AdvanceForm()
@@ -1553,6 +1554,12 @@ def org_contest_advance(ct_id: int):
prev_pion_query = (sess.query(db.Participation)
.filter(db.Participation.contest_id.in_([c.contest_id for c in prev_contests]))
.filter_by(state=db.PartState.active))
+ if prev_round.level < round.level:
+ prev_pion_query = (prev_pion_query
+ .join(db.Participant, and_(db.Participant.user_id == db.Participation.user_id,
+ db.Participant.year == round.year))
+ .join(db.RegionDescendant, and_(db.RegionDescendant.descendant == db.Participant.school,
+ db.RegionDescendant.region == contest.place_id)))
if want_select:
prev_pions = prev_pion_query.options(joinedload(db.Participation.user)).all()
else:
@@ -1581,9 +1588,9 @@ def org_contest_advance(ct_id: int):
really_inserted = 0
for pp in prev_pions:
# This incurs no real queries as we have all the contests cached
- prev_place_id = sess.query(db.Contest).get(pp.contest_id).place_id
- points = points_map[pp.user_id] if pp.user_id in points_map else None
- checked = points is not None and points >= form.boundary.data
+ prev_place_id = assert_not_none(sess.query(db.Contest).get(pp.contest_id)).place_id
+ points = points_map.get(pp.user_id, 0)
+ checked = points >= form.boundary.data
prev_pions_by_place_id[prev_place_id].append((pp, points, checked))
if want_execute and want_select:
@@ -1665,9 +1672,6 @@ def get_prev_round(round: db.Round) -> Optional[db.Round]:
if prev_round is None:
flash('Předchozí kolo nenalezeno', 'danger')
return None
- elif prev_round.level < round.level:
- flash('Předchozí kolo se koná ve vyšší oblasti než toto kolo', 'danger')
- return None
return prev_round
diff --git a/mo/web/org_round.py b/mo/web/org_round.py
index fec02c9526278dd38cc13074b99ca62bdbca776e..9b10d069daea4ab6d6f49a396c21cc92cdc791eb 100644
--- a/mo/web/org_round.py
+++ b/mo/web/org_round.py
@@ -678,14 +678,19 @@ def org_round_create_contests(round_id: int):
have_places_subq = (sess.query(db.Contest.place_id)
.filter_by(round=round))
- new_places = (sess.query(db.Place)
- .select_from(db.Contest)
- .filter(db.Contest.round == prev_round)
- .join(db.RegionDescendant, db.RegionDescendant.descendant == db.Contest.place_id)
- .join(db.Place, db.Place.place_id == db.RegionDescendant.region)
- .filter(db.Place.level == round.level)
- .filter(db.Place.place_id.notin_(have_places_subq))
- .all())
+ new_places_q = sess.query(db.Place).select_from(db.Contest).filter(db.Contest.round == prev_round)
+ if prev_round.level >= round.level:
+ new_places_q = (new_places_q
+ .join(db.RegionDescendant, db.RegionDescendant.descendant == db.Contest.place_id)
+ .join(db.Place, db.Place.place_id == db.RegionDescendant.region))
+ else:
+ new_places_q = (new_places_q
+ .join(db.RegionDescendant, db.RegionDescendant.region == db.Contest.place_id)
+ .join(db.Place, db.Place.place_id == db.RegionDescendant.descendant))
+ new_places = (new_places_q
+ .filter(db.Place.level == round.level)
+ .filter(db.Place.place_id.notin_(have_places_subq))
+ .all())
form = CreateContestsForm()
if form.validate_on_submit():