From f3a9096808dfe8bc5a4036951b66e040f58eb3bc Mon Sep 17 00:00:00 2001 From: chris48s Date: Mon, 9 Dec 2024 16:05:24 +0000 Subject: [PATCH] show correct opening times for City of London local elections --- locale/cy/LC_MESSAGES/django.po | 71 +++++++------- wcivf/apps/elections/models.py | 11 ++- .../elections/includes/_polling_place.html | 10 +- .../elections/tests/test_postcode_views.py | 97 +++++++++++++++++-- wcivf/apps/elections/views/postcode_view.py | 42 +++++++- 5 files changed, 177 insertions(+), 54 deletions(-) diff --git a/locale/cy/LC_MESSAGES/django.po b/locale/cy/LC_MESSAGES/django.po index d2db4376c..41e547747 100644 --- a/locale/cy/LC_MESSAGES/django.po +++ b/locale/cy/LC_MESSAGES/django.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-11-06 16:32+0000\n" +"POT-Creation-Date: 2024-12-09 15:05+0000\n" "PO-Revision-Date: 2022-03-24 09:04+0000\n" "Last-Translator: Sym Roe , 2022\n" "Language-Team: Welsh (https://www.transifex.com/democracy-club/teams/61326/" @@ -520,18 +520,19 @@ msgid "
%(polling_station_address)s
" msgstr "" #: wcivf/apps/elections/templates/elections/includes/_polling_place.html:57 -msgid "It will be open from 7am to 10pm." -msgstr "Bydd ar agor o 7am tan 10pm." +#, python-format +msgid "It will be open from %(open_time)s to %(close_time)s" +msgstr "Bydd ar agor o %(open_time)s tan %(close_time)s" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:63 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:65 msgid "and" msgstr "a" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:72 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:74 msgid "You don't need to take your poll card with you." msgstr "Nid oes angen i chi ddod â'ch cerdyn pleidleisio gyda chi." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:79 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:81 msgid "" "If you have a postal vote, you can hand it in at this polling station on " "election day up to 10pm. When handing in postal votes, you will need to " @@ -544,7 +545,7 @@ msgstr "" "faint o bleidleisiau post yr ydych yn eucyflwyno, a pham yr ydych yn " "cyflwyno'r pleidleisiau post hynny." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:89 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:91 msgid "" "If you have a postal vote, you can hand it in at this polling station on " "election day up to 10pm." @@ -552,18 +553,18 @@ msgstr "" "Os oes gennych bleidlais bost, gallwch ei chyflwyno yn yr orsaf bleidleisio " "hondiwrnod etholiad hyd at 10pm" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:93 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:95 msgid "" "Postal votes cannot be accepted at polling stations in Northern Ireland." msgstr "" "Ni ellir derbyn pleidleisiau post mewn gorsafoedd pleidleisio yng Ngogledd " "Iwerddon." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:95 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:97 msgid "Learn more about voting by post" msgstr "Dysgwch fwy am bleidleisio drwy'r post" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:98 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:100 #, python-format msgid "" "

You can find your polling station by " @@ -572,7 +573,7 @@ msgstr "" "

Gallwch ddod o hyd i'ch gorsaf bleidleisio drwy ddilyn y ddolen hon.

" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:106 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:108 #, python-format msgid "" "Polling stations are open from %(open_time)s till %(close_time)s " @@ -581,7 +582,7 @@ msgstr "" "Bydd gorsafoedd pleidleisio ar agor o %(open_time)s tan " "%(close_time)s heddiw." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:111 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:113 #, python-format msgid "" "

Your polling station in %(postcode)s depends on your address. Gwiriwch yr " "orsaf bleidleisio gywir ar gyfer eich cyfeiriad»

" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:115 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:117 msgid "" "You should get a \"poll card\" through the post telling you where to vote." msgstr "" "Dylech dderbyn \"cerdyn pleidleisio\" drwy'r post yn dweud ble y dylech chi " "bleidleisio." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:118 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:120 #, python-format msgid "" "If you haven't got one, or for questions about your poll card, polling " @@ -611,7 +612,7 @@ msgstr "" "ffonio'r Swyddfa Cofrestru Etholiadol %(council_phone)s." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:125 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:127 #, python-format msgid "" "If you haven't got one, or aren't sure where to vote, you should call " @@ -620,7 +621,7 @@ msgstr "" "Os nad oes gennych chi un, neu ddim yn siŵr ble i bleidleisio, dylech ffonio " "%(council_name)s ar %(council_phone)s." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:132 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:134 msgid "" "If you haven't got one, or aren't sure where to vote, you should call your " "local council." @@ -628,25 +629,25 @@ msgstr "" "Os nad oes gennych chi un, neu ddim yn siŵr ble i bleidleisio, dylech ffonio " "eich cyngor lleol." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:140 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:142 msgid "You will need photographic identification." msgstr "Bydd angen dull adnabod ffotograffig arnoch." -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:146 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:148 msgid "Read more about how to vote in Northern Ireland" msgstr "Darllenwch fwy am sut i bleidleisio yng Ngogledd Iwerddon" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:150 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:152 msgid "Read more about how to vote" msgstr "Darllenwch fwy am sut i bleidleisio" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:159 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:161 #, fuzzy #| msgid "Get walking directions from" msgid "Get directions" msgstr "Cael cyfarwyddiadau cerdded o" -#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:163 +#: wcivf/apps/elections/templates/elections/includes/_polling_place.html:165 #, fuzzy #| msgid "Get walking directions from" msgid "Get directions from" @@ -948,12 +949,12 @@ msgstr "" msgid "Citizenship" msgstr "Dinasyddiaeth" -#: wcivf/apps/elections/templates/elections/includes/_single_ballot.html:263 +#: wcivf/apps/elections/templates/elections/includes/_single_ballot.html:260 #: wcivf/apps/people/templates/people/includes/_person_about_card.html:7 msgid "Wikipedia" msgstr "Wikipedia" -#: wcivf/apps/elections/templates/elections/includes/_single_ballot.html:265 +#: wcivf/apps/elections/templates/elections/includes/_single_ballot.html:262 #: wcivf/apps/people/templates/people/includes/_person_about_card.html:9 msgid "Read more on Wikipedia" msgstr "Darllenwch fwy ar Wikipedia" @@ -1268,12 +1269,12 @@ msgstr "" msgid "Submit event" msgstr "" -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:6 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:7 #: wcivf/apps/hustings/templates/hustings/includes/_person.html:4 msgid "Election events" msgstr "Digwyddiadau etholiadol" -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:9 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:10 msgid "" "You can meet candidates and question them at events (often known as " "'hustings'). Here are some events that are taking place:" @@ -1281,24 +1282,24 @@ msgstr "" "Gallwch gwrdd ag ymgeiswyr a'u cwestiynu mewn digwyddiadau ar-lein (fe'u " "gelwir yn hystingiau). Dyma rai digwyddiadau sy'n digwydd:" -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:12 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:13 msgid "Events are reported by users, if you spot an error, please" msgstr "" -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:13 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:14 msgid "get in touch" msgstr "" -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:17 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:18 msgid "Do you know about any other events in the area? If so, please" msgstr "" -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:18 -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:26 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:19 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:27 msgid "tell us about them" msgstr "" -#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:24 +#: wcivf/apps/hustings/templates/hustings/includes/_ballot.html:25 msgid "Do you know about any events (often known as 'hustings')? If so, please" msgstr "" @@ -2752,6 +2753,9 @@ msgstr "" msgid "Upcoming Elections" msgstr "Etholiadau i ddod" +#~ msgid "It will be open from 7am to 10pm." +#~ msgstr "Bydd ar agor o 7am tan 10pm." + #, fuzzy #~| msgid "" #~| "For questions about your poll card, polling place, or about returning " @@ -2765,11 +2769,6 @@ msgstr "Etholiadau i ddod" #~ "bleidleisio, neu ynghylch dychwelyd eich pleidlais drwy'r post, " #~ "cysylltwch â'ch cyngor." -#, fuzzy -#~| msgid "It will be open from 7am to 10pm." -#~ msgid "It will be open from 8am to 8pm." -#~ msgstr "Bydd ar agor o 7am tan 10pm." - #~ msgid "" #~ "A parliamentary general election has been called for 4 July. Enter your " #~ "postcode to find your constituency and candidates." diff --git a/wcivf/apps/elections/models.py b/wcivf/apps/elections/models.py index fa93ad804..fe9aa9ec9 100644 --- a/wcivf/apps/elections/models.py +++ b/wcivf/apps/elections/models.py @@ -74,7 +74,7 @@ def in_past(self): @property def is_city_of_london_local_election(self): """ - Returns boolean for if the election is within City of London district. + Returns boolean for if the election is within City of London. The city often has different rules to other UK elections so it's useful to know when we need to special case. For further details: https://www.cityoflondon.gov.uk/about-us/voting-elections/elections/ward-elections @@ -83,15 +83,18 @@ def is_city_of_london_local_election(self): return "local.city-of-london" in self.slug @property - def is_city_of_london_parl_election(self): + def election_covers_city_of_london(self): """ - Returns boolean for if the election is within City of London district. + Returns boolean for if the election is in a parl or GLA constituency partially covering City of London. The city often has different rules to other UK elections so it's useful to know when we need to special case. For further details: https://www.cityoflondon.gov.uk/about-us/voting-elections/elections/ward-elections https://democracyclub.org.uk/blog/2017/03/22/eight-weird-things-about-tomorrows-city-london-elections/ """ - return "parl.cities-of-london-and-westminster" in self.slug + return ( + "parl.cities-of-london-and-westminster" in self.slug + or "gla.c.city-and-east" in self.slug + ) @property def polls_close(self): diff --git a/wcivf/apps/elections/templates/elections/includes/_polling_place.html b/wcivf/apps/elections/templates/elections/includes/_polling_place.html index e874e80d5..c5bf7152c 100644 --- a/wcivf/apps/elections/templates/elections/includes/_polling_place.html +++ b/wcivf/apps/elections/templates/elections/includes/_polling_place.html @@ -54,7 +54,11 @@

{% trans "Vote on polling day" %}

{{ polling_station_address }}
{% endblocktrans %}

- {% blocktrans trimmed %}It will be open from 7am to 10pm.{% endblocktrans %} + {% if not multiple_city_of_london_elections_on_next_poll_date %} + {% blocktrans trimmed with open_time=polling_station_opening_times.polls_open|time:"ga" close_time=polling_station_opening_times.polls_close|time:"ga" %} + It will be open from {{ open_time }} to {{ close_time }} + {% endblocktrans %} + {% endif %} {% for election in elections_by_date %} {{ election.grouper|naturalday:"\o\n l j F Y" }} @@ -102,8 +106,8 @@

{% trans "Vote on polling day" %}

{% endblocktrans %} {% else %} - {% if ballots_today and not multiple_city_of_london_elections_today %} - {% blocktrans trimmed with open_time=ballots_today.0.election.polls_open|time:"ga" close_time=ballots_today.0.election.polls_close|time:"ga" %} + {% if ballots_today and not multiple_city_of_london_elections_on_next_poll_date %} + {% blocktrans trimmed with open_time=polling_station_opening_times.polls_open|time:"ga" close_time=polling_station_opening_times.polls_close|time:"ga" %} Polling stations are open from {{ open_time }} till {{ close_time }} today. {% endblocktrans %} {% endif %} diff --git a/wcivf/apps/elections/tests/test_postcode_views.py b/wcivf/apps/elections/tests/test_postcode_views.py index e21461a4d..5d362b24e 100644 --- a/wcivf/apps/elections/tests/test_postcode_views.py +++ b/wcivf/apps/elections/tests/test_postcode_views.py @@ -192,6 +192,7 @@ def test_not_city_of_london_today(self, mock_response, client): ballot_paper_id="local.sheffield.ecclesall.2021-05-06", election__slug="local.sheffield.2021-05-06", election__election_date="2021-05-06", + post__territory="ENG", ) mock_response.json.return_value["dates"].append( @@ -210,6 +211,81 @@ def test_not_city_of_london_today(self, mock_response, client): response, "Polling stations are open from 7a.m. till 10p.m. today" ) + def test_polling_station_opening_times(self, mock_response, client): + post_election = PostElectionFactory( + ballot_paper_id="local.sheffield.ecclesall.2021-05-08", + election__slug="local.sheffield.2021-05-08", + election__election_date="2021-05-08", + post__territory="ENG", + ) + + mock_response.json.return_value["dates"].append( + { + "date": post_election.election.election_date, + "polling_station": { + "polling_station_known": True, + "custom_finder": False, + "report_problem_url": "http://wheredoivote.co.uk/report_problem/?source=testing&source_url=testing", + "station": { + "id": "QK", + "type": "Feature", + "geometry": None, + "properties": { + "address": "1 Made Up Street\nMade Up Town\nMade Up County", + "postcode": "MA1 1AA", + }, + }, + }, + "ballots": [{"ballot_paper_id": post_election.ballot_paper_id}], + } + ) + + response = client.get( + reverse("postcode_view", kwargs={"postcode": "s11 8qe"}), + follow=True, + ) + asserts.assertContains( + response, "It will be open from 7a.m. to 10p.m." + ) + + def test_polling_station_opening_times_city_of_london( + self, mock_response, client + ): + post_election = PostElectionFactory( + ballot_paper_id="local.city-of-london.aldgate.2021-05-08", + election__slug="local.city-of-london.2021-05-08", + election__election_date="2021-05-08", + post__territory="ENG", + ) + + mock_response.json.return_value["dates"].append( + { + "date": post_election.election.election_date, + "polling_station": { + "polling_station_known": True, + "custom_finder": False, + "report_problem_url": "http://wheredoivote.co.uk/report_problem/?source=testing&source_url=testing", + "station": { + "id": "QK", + "type": "Feature", + "geometry": None, + "properties": { + "address": "1 Made Up Street\nMade Up Town\nMade Up County", + "postcode": "MA1 1AA", + }, + }, + }, + "ballots": [{"ballot_paper_id": post_election.ballot_paper_id}], + } + ) + + response = client.get( + reverse("postcode_view", kwargs={"postcode": "e1 2ax"}), follow=True + ) + asserts.assertContains( + response, "It will be open from 8a.m. to 8p.m." + ) + def test_not_today(self, mock_response, client): post_election = PostElectionFactory( election__election_date="2021-05-07", @@ -547,11 +623,14 @@ def test_multiple_london_elections_same_day(self, view_obj, mocker): ) mocker.patch.object( view_obj, - "get_todays_ballots", + "get_ballots_for_next_date", return_value=list(PostElection.objects.all()), ) - assert view_obj.multiple_city_of_london_elections_today() is True + assert ( + view_obj.multiple_city_of_london_elections_on_next_poll_date() + is True + ) @pytest.mark.django_db def test_multiple_non_london_elections_same_day(self, view_obj, mocker): @@ -565,11 +644,14 @@ def test_multiple_non_london_elections_same_day(self, view_obj, mocker): ) mocker.patch.object( view_obj, - "get_todays_ballots", + "get_ballots_for_next_date", return_value=list(PostElection.objects.all()), ) - assert view_obj.multiple_city_of_london_elections_today() is False + assert ( + view_obj.multiple_city_of_london_elections_on_next_poll_date() + is False + ) @pytest.mark.django_db def test_multiple_non_london_elections_same_day_single_election( @@ -581,11 +663,14 @@ def test_multiple_non_london_elections_same_day_single_election( ) mocker.patch.object( view_obj, - "get_todays_ballots", + "get_ballots_for_next_date", return_value=list(PostElection.objects.all()), ) - assert view_obj.multiple_city_of_london_elections_today() is False + assert ( + view_obj.multiple_city_of_london_elections_on_next_poll_date() + is False + ) @pytest.fixture def post_elections(self, request): diff --git a/wcivf/apps/elections/views/postcode_view.py b/wcivf/apps/elections/views/postcode_view.py index a4286ca50..ceb2a347d 100644 --- a/wcivf/apps/elections/views/postcode_view.py +++ b/wcivf/apps/elections/views/postcode_view.py @@ -106,6 +106,9 @@ def get_context_data(self, **kwargs): for postelection in context["postelections"]: postelection.people = self.people_for_ballot(postelection) context["polling_station"] = self.ballot_dict.get("polling_station") + context[ + "polling_station_opening_times" + ] = self.get_polling_station_opening_times() context["council"] = self.ballot_dict.get("electoral_services") context["registration"] = self.ballot_dict.get("registration") context["postcode_location"] = self.ballot_dict.get( @@ -118,8 +121,8 @@ def get_context_data(self, **kwargs): context["ballots_today"] = self.get_todays_ballots() context[ - "multiple_city_of_london_elections_today" - ] = self.multiple_city_of_london_elections_today() + "multiple_city_of_london_elections_on_next_poll_date" + ] = self.multiple_city_of_london_elections_on_next_poll_date() context["referendums"] = list(self.get_referendums()) context["parish_council_election"] = self.get_parish_council_election() context["num_ballots"] = self.num_ballots() @@ -163,7 +166,36 @@ def get_referendums(self): for ballot in self.ballot_dict.get("ballots", []): yield from ballot.referendums.all() - def multiple_city_of_london_elections_today(self): + def get_ballots_for_next_date(self): + ballots = ( + self.get_ballot_dict() + .get("ballots") + .order_by("election__election_date") + ) + if not ballots: + return ballots + first_ballot_date = ballots[0].election.election_date + return ballots.filter(election__election_date=first_ballot_date) + + def get_polling_station_opening_times(self): + ballots = self.get_ballots_for_next_date() + if not ballots: + return { + "polls_open": None, + "polls_close": None, + } + for ballot in ballots: + if ballot.election.is_city_of_london_local_election: + return { + "polls_open": ballot.election.polls_open, + "polls_close": ballot.election.polls_close, + } + return { + "polls_open": ballots[0].election.polls_open, + "polls_close": ballots[0].election.polls_close, + } + + def multiple_city_of_london_elections_on_next_poll_date(self): """ Checks if there are multiple elections taking place today in the City of London. This is used to determine if it is safe to display polling @@ -171,7 +203,7 @@ def multiple_city_of_london_elections_today(self): it is unclear what time the polls would be open. See this issue for more info https://github.com/DemocracyClub/WhoCanIVoteFor/issues/441 """ - ballots = self.get_todays_ballots() + ballots = self.get_ballots_for_next_date() # if only one ballot can return early if len(ballots) <= 1: @@ -181,7 +213,7 @@ def multiple_city_of_london_elections_today(self): ballot for ballot in ballots if ballot.election.is_city_of_london_local_election - or ballot.election.is_city_of_london_parl_election + or ballot.election.election_covers_city_of_london ): return False