diff --git a/src/onegov/landsgemeinde/custom.py b/src/onegov/landsgemeinde/custom.py index 3bb6d71c29..23e8ef6c31 100644 --- a/src/onegov/landsgemeinde/custom.py +++ b/src/onegov/landsgemeinde/custom.py @@ -85,7 +85,7 @@ def get_top_navigation( yield ( # type:ignore[misc] Bunch(id=-1, access='public', published=True), Link( - text=_('Assemblies'), + text=_('Archive'), url=request.class_link(AssemblyCollection) ), () diff --git a/src/onegov/landsgemeinde/layouts/assembly.py b/src/onegov/landsgemeinde/layouts/assembly.py index 36d82d8edf..ea6484bd89 100644 --- a/src/onegov/landsgemeinde/layouts/assembly.py +++ b/src/onegov/landsgemeinde/layouts/assembly.py @@ -19,7 +19,7 @@ class AssemblyCollectionLayout(DefaultLayout): @cached_property def title(self) -> str: - return _('Assemblies') + return _('Archive') @cached_property def og_description(self) -> str: @@ -74,7 +74,7 @@ def breadcrumbs(self) -> list[Link]: return [ Link(_('Homepage'), self.homepage_url), Link( - _('Assemblies'), + _('Archive'), self.request.link(self.assembly_collection()) ), Link(self.title, self.request.link(self.model)) diff --git a/src/onegov/landsgemeinde/templates/macros.pt b/src/onegov/landsgemeinde/templates/macros.pt index 43192eadd6..fd81b1e949 100644 --- a/src/onegov/landsgemeinde/templates/macros.pt +++ b/src/onegov/landsgemeinde/templates/macros.pt @@ -244,7 +244,6 @@ -
Auskunft
more diff --git a/src/onegov/search/indexer.py b/src/onegov/search/indexer.py index 067e62849d..9ace8171ba 100644 --- a/src/onegov/search/indexer.py +++ b/src/onegov/search/indexer.py @@ -10,6 +10,8 @@ from operator import itemgetter from queue import Queue, Empty, Full +from sqlalchemy.orm.exc import ObjectDeletedError + from onegov.core.utils import is_non_string_iterable from onegov.search import index_log, log, Searchable, utils from onegov.search.errors import SearchOfflineError @@ -907,59 +909,65 @@ def put(self, translation: 'Task') -> None: log.error('The orm event translator queue is full!') def index(self, schema: str, obj: Searchable) -> None: - if obj.es_skip: - return + try: + if obj.es_skip: + return - if obj.es_language == 'auto': - language = self.detector.detect_object_language(obj) - else: - language = obj.es_language + if obj.es_language == 'auto': + language = self.detector.detect_object_language(obj) + else: + language = obj.es_language + + translation: IndexTask = { + 'action': 'index', + 'id': getattr(obj, obj.es_id), + 'id_key': obj.es_id, + 'schema': schema, + 'type_name': obj.es_type_name, # FIXME: not needed for fts + 'tablename': obj.__tablename__, # type:ignore[attr-defined] + 'language': language, + 'properties': {} + } - translation: IndexTask = { - 'action': 'index', - 'id': getattr(obj, obj.es_id), - 'id_key': obj.es_id, - 'schema': schema, - 'type_name': obj.es_type_name, # FIXME: not needed for fts - 'tablename': obj.__tablename__, # type:ignore[attr-defined] - 'language': language, - 'properties': {} - } + mapping_ = self.mappings[obj.es_type_name].for_language(language) - mapping_ = self.mappings[obj.es_type_name].for_language(language) + for prop, mapping in mapping_.items(): - for prop, mapping in mapping_.items(): + if prop == 'es_suggestion': + continue - if prop == 'es_suggestion': - continue + convert = self.converters.get(mapping['type'], lambda v: v) + raw = getattr(obj, prop) - convert = self.converters.get(mapping['type'], lambda v: v) - raw = getattr(obj, prop) + if is_non_string_iterable(raw): + translation['properties'][prop] = [convert(v) for v in raw] + else: + translation['properties'][prop] = convert(raw) - if is_non_string_iterable(raw): - translation['properties'][prop] = [convert(v) for v in raw] + if obj.es_public: + contexts = {'es_suggestion_context': ['public']} else: - translation['properties'][prop] = convert(raw) + contexts = {'es_suggestion_context': ['private']} - if obj.es_public: - contexts = {'es_suggestion_context': ['public']} - else: - contexts = {'es_suggestion_context': ['private']} - - suggestion = obj.es_suggestion + suggestion = obj.es_suggestion - if is_non_string_iterable(suggestion): - translation['properties']['es_suggestion'] = { - 'input': suggestion, - 'contexts': contexts - } - else: - translation['properties']['es_suggestion'] = { - 'input': [suggestion], - 'contexts': contexts - } + if is_non_string_iterable(suggestion): + translation['properties']['es_suggestion'] = { + 'input': suggestion, + 'contexts': contexts + } + else: + translation['properties']['es_suggestion'] = { + 'input': [suggestion], + 'contexts': contexts + } - self.put(translation) + self.put(translation) + except ObjectDeletedError as ex: + if hasattr(obj, 'id'): + log.error(f'Object {obj.id} was deleted before indexing: {ex}') + else: + log.error(f'Object {obj} was deleted before indexing: {ex}') def delete(self, schema: str, obj: Searchable) -> None: diff --git a/tests/onegov/fsi/test_models.py b/tests/onegov/fsi/test_models.py index 1b4652dffd..00e0afb9c7 100644 --- a/tests/onegov/fsi/test_models.py +++ b/tests/onegov/fsi/test_models.py @@ -1,4 +1,6 @@ import datetime + +from freezegun import freeze_time from sedate import utcnow from onegov.fsi.models.course_attendee import CourseAttendee @@ -44,57 +46,67 @@ def test_attendee( def test_course_event(scenario): - - scenario.add_attendee() - scenario.add_course(name='Course') - scenario.add_course_event(scenario.latest_course, max_attendees=20) - delta = datetime.timedelta(days=366) - - # Add a participant via a subscription - event = scenario.latest_event - scenario.add_subscription(event, None, dummy_desc='Placeholder') - scenario.add_subscription(event, scenario.latest_attendee) - - # Add inactive attendee - scenario.add_attendee(active=False) - scenario.add_subscription(event, scenario.latest_attendee) - - scenario.commit() - scenario.refresh() - - event = scenario.latest_event - assert event.subscriptions.count() == 3 - assert event.attendees.count() == 2 - assert event.available_seats == 20 - 3 - assert event.possible_subscribers().first() is None - - # Test possible and excluded subscribers - scenario.add_attendee(username='2@example.org') - attendee_2 = scenario.latest_attendee - - # event = scenario.latest_event - assert event.course - assert event.possible_subscribers(year=event.end.year).all() == [ - attendee_2 - ] - - scenario.add_course_event( - scenario.latest_course, - start=event.start + delta, end=event.end + delta, - max_attendees=20 - ) - event2 = scenario.latest_event - - # Event for a year later, exclude the one who has a subscription to this - # course - assert event.possible_subscribers(year=event.end.year + 1).count() == 1 - assert event2.possible_subscribers(year=event.end.year).count() == 1 - assert event2.possible_subscribers(year=event.end.year + 1).count() == 2 - assert event.possible_subscribers(external_only=True).count() == 0 - assert event.excluded_subscribers().count() == 2 - assert event2.possible_subscribers().first() == attendee_2 - - assert scenario.latest_course.future_events.count() == 2 + # if current date is last or second last day of the year, then freeze to + # 28th of december + if utcnow().date().month == 12 and utcnow().date().day in (30, 31): + freeze_date = '2024-12-28' + else: + freeze_date = utcnow().date() + + with freeze_time(freeze_date): + scenario.add_attendee() + scenario.add_course(name='Course') + scenario.add_course_event(scenario.latest_course, max_attendees=20) + delta = datetime.timedelta(days=366) + + # Add a participant via a subscription + event = scenario.latest_event + scenario.add_subscription(event, None, dummy_desc='Placeholder') + scenario.add_subscription(event, scenario.latest_attendee) + + # Add inactive attendee + scenario.add_attendee(active=False) + scenario.add_subscription(event, scenario.latest_attendee) + + scenario.commit() + scenario.refresh() + + event = scenario.latest_event + assert event.subscriptions.count() == 3 + assert event.attendees.count() == 2 + assert event.available_seats == 20 - 3 + assert event.possible_subscribers().first() is None + + # Test possible and excluded subscribers + scenario.add_attendee(username='2@example.org') + attendee_2 = scenario.latest_attendee + + # event = scenario.latest_event + assert event.course + assert event.possible_subscribers(year=event.end.year).all() == [ + attendee_2 + ] + + scenario.add_course_event( + scenario.latest_course, + start=event.start + delta, end=event.end + delta, + max_attendees=20 + ) + event2 = scenario.latest_event + + # Event for a year later, exclude the one who has a subscription to + # this course + assert event.possible_subscribers( + year=event.end.year + 1).count() == 1 + assert event2.possible_subscribers( + year=event.end.year).count() == 1 + assert event2.possible_subscribers( + year=event.end.year + 1).count() == 2 + assert event.possible_subscribers(external_only=True).count() == 0 + assert event.excluded_subscribers().count() == 2 + assert event2.possible_subscribers().first() == attendee_2 + + assert scenario.latest_course.future_events.count() == 2 def test_subscription(session, attendee, course_event): diff --git a/tests/onegov/landsgemeinde/test_views.py b/tests/onegov/landsgemeinde/test_views.py index 3c02cdb96a..e5ac61231e 100644 --- a/tests/onegov/landsgemeinde/test_views.py +++ b/tests/onegov/landsgemeinde/test_views.py @@ -18,13 +18,13 @@ def assert_last_modified(): client_with_es.login('admin@example.org', 'hunter2') - page = client_with_es.get('/').click('Landsgemeinden') + page = client_with_es.get('/').click('Archiv') assert 'Noch keine Landsgemeinden erfasst.' in page assert 'Zum Liveticker' not in page # add assembly with freeze_time('2023-05-07 9:30'): - page = page.click('Landsgemeinde', index=1) + page = page.click('Landsgemeinde') page.form['date'] = '2023-05-07' page.form['state'] = 'ongoing' page.form['overview'] = '

Lorem ipsum

' @@ -167,7 +167,7 @@ def assert_last_modified(): # delete agenda item with freeze_time('2023-05-07 9:37'): page.click('Löschen') - page = page.click('Landsgemeinde', index=2) + page = page.click('Landsgemeinde', index=1) assert '

Lorem ipsum dolor sit amet

' in page assert 'A. consectetur adipiscing' not in page assert_last_modified() @@ -175,7 +175,7 @@ def assert_last_modified(): # delete landsgemeinde with freeze_time('2023-05-07 9:38'): page.click('Löschen') - page = page.click('Landsgemeinden', index=0) + page = page.click('Archiv', index=0) assert 'Noch keine Landsgemeinden erfasst.' in page @@ -189,8 +189,8 @@ def test_view_pages_cache(landsgemeinde_app): # add assembly client.login('admin@example.org', 'hunter2') - page = client.get('/').click('Landsgemeinden') - page = page.click('Landsgemeinde', index=1) + page = client.get('/').click('Archiv') + page = page.click('Landsgemeinde') page.form['date'] = '2023-05-07' page.form['state'] = 'completed' page.form['overview'] = 'Lorem'